1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate * 26*7c478bd9Sstevel@tonic-gate * STREAMS Crypto Module 27*7c478bd9Sstevel@tonic-gate * 28*7c478bd9Sstevel@tonic-gate * This module is used to facilitate Kerberos encryption 29*7c478bd9Sstevel@tonic-gate * operations for the telnet daemon and rlogin daemon. 30*7c478bd9Sstevel@tonic-gate * Because the Solaris telnet and rlogin daemons run mostly 31*7c478bd9Sstevel@tonic-gate * in-kernel via 'telmod' and 'rlmod', this module must be 32*7c478bd9Sstevel@tonic-gate * pushed on the STREAM *below* telmod or rlmod. 33*7c478bd9Sstevel@tonic-gate * 34*7c478bd9Sstevel@tonic-gate * Parts of the 3DES key derivation code are covered by the 35*7c478bd9Sstevel@tonic-gate * following copyright. 36*7c478bd9Sstevel@tonic-gate * 37*7c478bd9Sstevel@tonic-gate * Copyright (C) 1998 by the FundsXpress, INC. 38*7c478bd9Sstevel@tonic-gate * 39*7c478bd9Sstevel@tonic-gate * All rights reserved. 40*7c478bd9Sstevel@tonic-gate * 41*7c478bd9Sstevel@tonic-gate * Export of this software from the United States of America may require 42*7c478bd9Sstevel@tonic-gate * a specific license from the United States Government. It is the 43*7c478bd9Sstevel@tonic-gate * responsibility of any person or organization contemplating export to 44*7c478bd9Sstevel@tonic-gate * obtain such a license before exporting. 45*7c478bd9Sstevel@tonic-gate * 46*7c478bd9Sstevel@tonic-gate * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 47*7c478bd9Sstevel@tonic-gate * distribute this software and its documentation for any purpose and 48*7c478bd9Sstevel@tonic-gate * without fee is hereby granted, provided that the above copyright 49*7c478bd9Sstevel@tonic-gate * notice appear in all copies and that both that copyright notice and 50*7c478bd9Sstevel@tonic-gate * this permission notice appear in supporting documentation, and that 51*7c478bd9Sstevel@tonic-gate * the name of FundsXpress. not be used in advertising or publicity pertaining 52*7c478bd9Sstevel@tonic-gate * to distribution of the software without specific, written prior 53*7c478bd9Sstevel@tonic-gate * permission. FundsXpress makes no representations about the suitability of 54*7c478bd9Sstevel@tonic-gate * this software for any purpose. It is provided "as is" without express 55*7c478bd9Sstevel@tonic-gate * or implied warranty. 56*7c478bd9Sstevel@tonic-gate * 57*7c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 58*7c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 59*7c478bd9Sstevel@tonic-gate * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 60*7c478bd9Sstevel@tonic-gate */ 61*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 62*7c478bd9Sstevel@tonic-gate 63*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 64*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 65*7c478bd9Sstevel@tonic-gate #include <sys/errno.h> 66*7c478bd9Sstevel@tonic-gate #include <sys/debug.h> 67*7c478bd9Sstevel@tonic-gate #include <sys/time.h> 68*7c478bd9Sstevel@tonic-gate #include <sys/stropts.h> 69*7c478bd9Sstevel@tonic-gate #include <sys/stream.h> 70*7c478bd9Sstevel@tonic-gate #include <sys/strsubr.h> 71*7c478bd9Sstevel@tonic-gate #include <sys/strlog.h> 72*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 73*7c478bd9Sstevel@tonic-gate #include <sys/conf.h> 74*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 75*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 76*7c478bd9Sstevel@tonic-gate #include <sys/strsun.h> 77*7c478bd9Sstevel@tonic-gate #include <sys/random.h> 78*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 79*7c478bd9Sstevel@tonic-gate #include <sys/byteorder.h> 80*7c478bd9Sstevel@tonic-gate #include <sys/cryptmod.h> 81*7c478bd9Sstevel@tonic-gate #include <sys/crc32.h> 82*7c478bd9Sstevel@tonic-gate #include <sys/policy.h> 83*7c478bd9Sstevel@tonic-gate 84*7c478bd9Sstevel@tonic-gate #include <sys/crypto/api.h> 85*7c478bd9Sstevel@tonic-gate 86*7c478bd9Sstevel@tonic-gate #include <sys/strft.h> 87*7c478bd9Sstevel@tonic-gate /* 88*7c478bd9Sstevel@tonic-gate * Function prototypes. 89*7c478bd9Sstevel@tonic-gate */ 90*7c478bd9Sstevel@tonic-gate static int cryptmodopen(queue_t *, dev_t *, int, int, cred_t *); 91*7c478bd9Sstevel@tonic-gate static void cryptmodrput(queue_t *, mblk_t *); 92*7c478bd9Sstevel@tonic-gate static void cryptmodwput(queue_t *, mblk_t *); 93*7c478bd9Sstevel@tonic-gate static int cryptmodclose(queue_t *); 94*7c478bd9Sstevel@tonic-gate static int cryptmodwsrv(queue_t *); 95*7c478bd9Sstevel@tonic-gate static int cryptmodrsrv(queue_t *); 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate static mblk_t *do_encrypt(queue_t *q, mblk_t *mp); 98*7c478bd9Sstevel@tonic-gate static mblk_t *do_decrypt(queue_t *q, mblk_t *mp); 99*7c478bd9Sstevel@tonic-gate 100*7c478bd9Sstevel@tonic-gate #define CRYPTMOD_ID 5150 101*7c478bd9Sstevel@tonic-gate 102*7c478bd9Sstevel@tonic-gate #define CFB_BLKSZ 8 103*7c478bd9Sstevel@tonic-gate 104*7c478bd9Sstevel@tonic-gate #define K5CLENGTH 5 105*7c478bd9Sstevel@tonic-gate 106*7c478bd9Sstevel@tonic-gate static struct module_info cryptmod_minfo = { 107*7c478bd9Sstevel@tonic-gate CRYPTMOD_ID, /* mi_idnum */ 108*7c478bd9Sstevel@tonic-gate "cryptmod", /* mi_idname */ 109*7c478bd9Sstevel@tonic-gate 0, /* mi_minpsz */ 110*7c478bd9Sstevel@tonic-gate INFPSZ, /* mi_maxpsz */ 111*7c478bd9Sstevel@tonic-gate 65536, /* mi_hiwat */ 112*7c478bd9Sstevel@tonic-gate 1024 /* mi_lowat */ 113*7c478bd9Sstevel@tonic-gate }; 114*7c478bd9Sstevel@tonic-gate 115*7c478bd9Sstevel@tonic-gate static struct qinit cryptmod_rinit = { 116*7c478bd9Sstevel@tonic-gate (int (*)())cryptmodrput, /* qi_putp */ 117*7c478bd9Sstevel@tonic-gate cryptmodrsrv, /* qi_svc */ 118*7c478bd9Sstevel@tonic-gate cryptmodopen, /* qi_qopen */ 119*7c478bd9Sstevel@tonic-gate cryptmodclose, /* qi_qclose */ 120*7c478bd9Sstevel@tonic-gate NULL, /* qi_qadmin */ 121*7c478bd9Sstevel@tonic-gate &cryptmod_minfo, /* qi_minfo */ 122*7c478bd9Sstevel@tonic-gate NULL /* qi_mstat */ 123*7c478bd9Sstevel@tonic-gate }; 124*7c478bd9Sstevel@tonic-gate 125*7c478bd9Sstevel@tonic-gate static struct qinit cryptmod_winit = { 126*7c478bd9Sstevel@tonic-gate (int (*)())cryptmodwput, /* qi_putp */ 127*7c478bd9Sstevel@tonic-gate cryptmodwsrv, /* qi_srvp */ 128*7c478bd9Sstevel@tonic-gate NULL, /* qi_qopen */ 129*7c478bd9Sstevel@tonic-gate NULL, /* qi_qclose */ 130*7c478bd9Sstevel@tonic-gate NULL, /* qi_qadmin */ 131*7c478bd9Sstevel@tonic-gate &cryptmod_minfo, /* qi_minfo */ 132*7c478bd9Sstevel@tonic-gate NULL /* qi_mstat */ 133*7c478bd9Sstevel@tonic-gate }; 134*7c478bd9Sstevel@tonic-gate 135*7c478bd9Sstevel@tonic-gate static struct streamtab cryptmod_info = { 136*7c478bd9Sstevel@tonic-gate &cryptmod_rinit, /* st_rdinit */ 137*7c478bd9Sstevel@tonic-gate &cryptmod_winit, /* st_wrinit */ 138*7c478bd9Sstevel@tonic-gate NULL, /* st_muxrinit */ 139*7c478bd9Sstevel@tonic-gate NULL /* st_muxwinit */ 140*7c478bd9Sstevel@tonic-gate }; 141*7c478bd9Sstevel@tonic-gate 142*7c478bd9Sstevel@tonic-gate typedef struct { 143*7c478bd9Sstevel@tonic-gate uint_t hash_len; 144*7c478bd9Sstevel@tonic-gate uint_t confound_len; 145*7c478bd9Sstevel@tonic-gate int (*hashfunc)(); 146*7c478bd9Sstevel@tonic-gate } hash_info_t; 147*7c478bd9Sstevel@tonic-gate 148*7c478bd9Sstevel@tonic-gate #define MAX_CKSUM_LEN 20 149*7c478bd9Sstevel@tonic-gate #define CONFOUNDER_LEN 8 150*7c478bd9Sstevel@tonic-gate 151*7c478bd9Sstevel@tonic-gate #define SHA1_HASHSIZE 20 152*7c478bd9Sstevel@tonic-gate #define MD5_HASHSIZE 16 153*7c478bd9Sstevel@tonic-gate #define CRC32_HASHSIZE 4 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate static int crc32_calc(uchar_t *, uchar_t *, uint_t); 156*7c478bd9Sstevel@tonic-gate static int md5_calc(uchar_t *, uchar_t *, uint_t); 157*7c478bd9Sstevel@tonic-gate static int sha1_calc(uchar_t *, uchar_t *, uint_t); 158*7c478bd9Sstevel@tonic-gate 159*7c478bd9Sstevel@tonic-gate static hash_info_t null_hash = {0, 0, NULL}; 160*7c478bd9Sstevel@tonic-gate static hash_info_t crc32_hash = {CRC32_HASHSIZE, CONFOUNDER_LEN, crc32_calc}; 161*7c478bd9Sstevel@tonic-gate static hash_info_t md5_hash = {MD5_HASHSIZE, CONFOUNDER_LEN, md5_calc}; 162*7c478bd9Sstevel@tonic-gate static hash_info_t sha1_hash = {SHA1_HASHSIZE, CONFOUNDER_LEN, sha1_calc}; 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate static crypto_mech_type_t sha1_hmac_mech = CRYPTO_MECH_INVALID; 165*7c478bd9Sstevel@tonic-gate static crypto_mech_type_t md5_hmac_mech = CRYPTO_MECH_INVALID; 166*7c478bd9Sstevel@tonic-gate static crypto_mech_type_t sha1_hash_mech = CRYPTO_MECH_INVALID; 167*7c478bd9Sstevel@tonic-gate static crypto_mech_type_t md5_hash_mech = CRYPTO_MECH_INVALID; 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate static int kef_crypt(struct cipher_data_t *, void *, 170*7c478bd9Sstevel@tonic-gate crypto_data_format_t, size_t, int); 171*7c478bd9Sstevel@tonic-gate static mblk_t * 172*7c478bd9Sstevel@tonic-gate arcfour_hmac_md5_encrypt(queue_t *, struct tmodinfo *, 173*7c478bd9Sstevel@tonic-gate mblk_t *, hash_info_t *); 174*7c478bd9Sstevel@tonic-gate static mblk_t * 175*7c478bd9Sstevel@tonic-gate arcfour_hmac_md5_decrypt(queue_t *, struct tmodinfo *, 176*7c478bd9Sstevel@tonic-gate mblk_t *, hash_info_t *); 177*7c478bd9Sstevel@tonic-gate 178*7c478bd9Sstevel@tonic-gate static int 179*7c478bd9Sstevel@tonic-gate do_hmac(crypto_mech_type_t, crypto_key_t *, char *, int, char *, int); 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate /* 182*7c478bd9Sstevel@tonic-gate * This is the loadable module wrapper. 183*7c478bd9Sstevel@tonic-gate */ 184*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 185*7c478bd9Sstevel@tonic-gate 186*7c478bd9Sstevel@tonic-gate static struct fmodsw fsw = { 187*7c478bd9Sstevel@tonic-gate "cryptmod", 188*7c478bd9Sstevel@tonic-gate &cryptmod_info, 189*7c478bd9Sstevel@tonic-gate D_MP | D_MTQPAIR 190*7c478bd9Sstevel@tonic-gate }; 191*7c478bd9Sstevel@tonic-gate 192*7c478bd9Sstevel@tonic-gate /* 193*7c478bd9Sstevel@tonic-gate * Module linkage information for the kernel. 194*7c478bd9Sstevel@tonic-gate */ 195*7c478bd9Sstevel@tonic-gate static struct modlstrmod modlstrmod = { 196*7c478bd9Sstevel@tonic-gate &mod_strmodops, 197*7c478bd9Sstevel@tonic-gate "STREAMS encryption module %I%", 198*7c478bd9Sstevel@tonic-gate &fsw 199*7c478bd9Sstevel@tonic-gate }; 200*7c478bd9Sstevel@tonic-gate 201*7c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 202*7c478bd9Sstevel@tonic-gate MODREV_1, 203*7c478bd9Sstevel@tonic-gate &modlstrmod, 204*7c478bd9Sstevel@tonic-gate NULL 205*7c478bd9Sstevel@tonic-gate }; 206*7c478bd9Sstevel@tonic-gate 207*7c478bd9Sstevel@tonic-gate int 208*7c478bd9Sstevel@tonic-gate _init(void) 209*7c478bd9Sstevel@tonic-gate { 210*7c478bd9Sstevel@tonic-gate return (mod_install(&modlinkage)); 211*7c478bd9Sstevel@tonic-gate } 212*7c478bd9Sstevel@tonic-gate 213*7c478bd9Sstevel@tonic-gate int 214*7c478bd9Sstevel@tonic-gate _fini(void) 215*7c478bd9Sstevel@tonic-gate { 216*7c478bd9Sstevel@tonic-gate return (mod_remove(&modlinkage)); 217*7c478bd9Sstevel@tonic-gate } 218*7c478bd9Sstevel@tonic-gate 219*7c478bd9Sstevel@tonic-gate int 220*7c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 221*7c478bd9Sstevel@tonic-gate { 222*7c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 223*7c478bd9Sstevel@tonic-gate } 224*7c478bd9Sstevel@tonic-gate 225*7c478bd9Sstevel@tonic-gate static void 226*7c478bd9Sstevel@tonic-gate cleanup(struct cipher_data_t *cd) 227*7c478bd9Sstevel@tonic-gate { 228*7c478bd9Sstevel@tonic-gate if (cd->key != NULL) { 229*7c478bd9Sstevel@tonic-gate bzero(cd->key, cd->keylen); 230*7c478bd9Sstevel@tonic-gate kmem_free(cd->key, cd->keylen); 231*7c478bd9Sstevel@tonic-gate cd->key = NULL; 232*7c478bd9Sstevel@tonic-gate } 233*7c478bd9Sstevel@tonic-gate 234*7c478bd9Sstevel@tonic-gate if (cd->ckey != NULL) { 235*7c478bd9Sstevel@tonic-gate /* 236*7c478bd9Sstevel@tonic-gate * ckey is a crypto_key_t structure which references 237*7c478bd9Sstevel@tonic-gate * "cd->key" for its raw key data. Since that was already 238*7c478bd9Sstevel@tonic-gate * cleared out, we don't need another "bzero" here. 239*7c478bd9Sstevel@tonic-gate */ 240*7c478bd9Sstevel@tonic-gate kmem_free(cd->ckey, sizeof (crypto_key_t)); 241*7c478bd9Sstevel@tonic-gate cd->ckey = NULL; 242*7c478bd9Sstevel@tonic-gate } 243*7c478bd9Sstevel@tonic-gate 244*7c478bd9Sstevel@tonic-gate if (cd->block != NULL) { 245*7c478bd9Sstevel@tonic-gate kmem_free(cd->block, cd->blocklen); 246*7c478bd9Sstevel@tonic-gate cd->block = NULL; 247*7c478bd9Sstevel@tonic-gate } 248*7c478bd9Sstevel@tonic-gate 249*7c478bd9Sstevel@tonic-gate if (cd->saveblock != NULL) { 250*7c478bd9Sstevel@tonic-gate kmem_free(cd->saveblock, cd->blocklen); 251*7c478bd9Sstevel@tonic-gate cd->saveblock = NULL; 252*7c478bd9Sstevel@tonic-gate } 253*7c478bd9Sstevel@tonic-gate 254*7c478bd9Sstevel@tonic-gate if (cd->ivec != NULL) { 255*7c478bd9Sstevel@tonic-gate kmem_free(cd->ivec, cd->ivlen); 256*7c478bd9Sstevel@tonic-gate cd->ivec = NULL; 257*7c478bd9Sstevel@tonic-gate } 258*7c478bd9Sstevel@tonic-gate 259*7c478bd9Sstevel@tonic-gate if (cd->d_encr_key.ck_data != NULL) { 260*7c478bd9Sstevel@tonic-gate bzero(cd->d_encr_key.ck_data, cd->keylen); 261*7c478bd9Sstevel@tonic-gate kmem_free(cd->d_encr_key.ck_data, cd->keylen); 262*7c478bd9Sstevel@tonic-gate } 263*7c478bd9Sstevel@tonic-gate 264*7c478bd9Sstevel@tonic-gate if (cd->d_hmac_key.ck_data != NULL) { 265*7c478bd9Sstevel@tonic-gate bzero(cd->d_hmac_key.ck_data, cd->keylen); 266*7c478bd9Sstevel@tonic-gate kmem_free(cd->d_hmac_key.ck_data, cd->keylen); 267*7c478bd9Sstevel@tonic-gate } 268*7c478bd9Sstevel@tonic-gate 269*7c478bd9Sstevel@tonic-gate if (cd->enc_tmpl != NULL) 270*7c478bd9Sstevel@tonic-gate (void) crypto_destroy_ctx_template(cd->enc_tmpl); 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate if (cd->hmac_tmpl != NULL) 273*7c478bd9Sstevel@tonic-gate (void) crypto_destroy_ctx_template(cd->hmac_tmpl); 274*7c478bd9Sstevel@tonic-gate 275*7c478bd9Sstevel@tonic-gate if (cd->ctx != NULL) { 276*7c478bd9Sstevel@tonic-gate crypto_cancel_ctx(cd->ctx); 277*7c478bd9Sstevel@tonic-gate cd->ctx = NULL; 278*7c478bd9Sstevel@tonic-gate } 279*7c478bd9Sstevel@tonic-gate } 280*7c478bd9Sstevel@tonic-gate 281*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 282*7c478bd9Sstevel@tonic-gate static int 283*7c478bd9Sstevel@tonic-gate cryptmodopen(queue_t *rq, dev_t *dev, int oflag, int sflag, cred_t *crp) 284*7c478bd9Sstevel@tonic-gate { 285*7c478bd9Sstevel@tonic-gate struct tmodinfo *tmi; 286*7c478bd9Sstevel@tonic-gate ASSERT(rq); 287*7c478bd9Sstevel@tonic-gate 288*7c478bd9Sstevel@tonic-gate if (sflag != MODOPEN) 289*7c478bd9Sstevel@tonic-gate return (EINVAL); 290*7c478bd9Sstevel@tonic-gate 291*7c478bd9Sstevel@tonic-gate (void) (STRLOG(CRYPTMOD_ID, 0, 5, SL_TRACE|SL_NOTE, 292*7c478bd9Sstevel@tonic-gate "cryptmodopen: opening module(PID %d)", 293*7c478bd9Sstevel@tonic-gate ddi_get_pid())); 294*7c478bd9Sstevel@tonic-gate 295*7c478bd9Sstevel@tonic-gate if (rq->q_ptr != NULL) { 296*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "cryptmodopen: already opened"); 297*7c478bd9Sstevel@tonic-gate return (0); 298*7c478bd9Sstevel@tonic-gate } 299*7c478bd9Sstevel@tonic-gate 300*7c478bd9Sstevel@tonic-gate /* 301*7c478bd9Sstevel@tonic-gate * Allocate and initialize per-Stream structure. 302*7c478bd9Sstevel@tonic-gate */ 303*7c478bd9Sstevel@tonic-gate tmi = (struct tmodinfo *)kmem_zalloc(sizeof (struct tmodinfo), 304*7c478bd9Sstevel@tonic-gate KM_SLEEP); 305*7c478bd9Sstevel@tonic-gate 306*7c478bd9Sstevel@tonic-gate tmi->enc_data.method = CRYPT_METHOD_NONE; 307*7c478bd9Sstevel@tonic-gate tmi->dec_data.method = CRYPT_METHOD_NONE; 308*7c478bd9Sstevel@tonic-gate 309*7c478bd9Sstevel@tonic-gate tmi->ready = (CRYPT_READ_READY | CRYPT_WRITE_READY); 310*7c478bd9Sstevel@tonic-gate 311*7c478bd9Sstevel@tonic-gate rq->q_ptr = WR(rq)->q_ptr = tmi; 312*7c478bd9Sstevel@tonic-gate 313*7c478bd9Sstevel@tonic-gate sha1_hmac_mech = crypto_mech2id(SUN_CKM_SHA1_HMAC); 314*7c478bd9Sstevel@tonic-gate md5_hmac_mech = crypto_mech2id(SUN_CKM_MD5_HMAC); 315*7c478bd9Sstevel@tonic-gate sha1_hash_mech = crypto_mech2id(SUN_CKM_SHA1); 316*7c478bd9Sstevel@tonic-gate md5_hash_mech = crypto_mech2id(SUN_CKM_MD5); 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate qprocson(rq); 319*7c478bd9Sstevel@tonic-gate 320*7c478bd9Sstevel@tonic-gate return (0); 321*7c478bd9Sstevel@tonic-gate } 322*7c478bd9Sstevel@tonic-gate 323*7c478bd9Sstevel@tonic-gate static int 324*7c478bd9Sstevel@tonic-gate cryptmodclose(queue_t *rq) 325*7c478bd9Sstevel@tonic-gate { 326*7c478bd9Sstevel@tonic-gate struct tmodinfo *tmi = (struct tmodinfo *)rq->q_ptr; 327*7c478bd9Sstevel@tonic-gate ASSERT(tmi); 328*7c478bd9Sstevel@tonic-gate 329*7c478bd9Sstevel@tonic-gate qprocsoff(rq); 330*7c478bd9Sstevel@tonic-gate 331*7c478bd9Sstevel@tonic-gate cleanup(&tmi->enc_data); 332*7c478bd9Sstevel@tonic-gate cleanup(&tmi->dec_data); 333*7c478bd9Sstevel@tonic-gate 334*7c478bd9Sstevel@tonic-gate kmem_free(tmi, sizeof (struct tmodinfo)); 335*7c478bd9Sstevel@tonic-gate rq->q_ptr = WR(rq)->q_ptr = NULL; 336*7c478bd9Sstevel@tonic-gate 337*7c478bd9Sstevel@tonic-gate return (0); 338*7c478bd9Sstevel@tonic-gate } 339*7c478bd9Sstevel@tonic-gate 340*7c478bd9Sstevel@tonic-gate /* 341*7c478bd9Sstevel@tonic-gate * plaintext_offset 342*7c478bd9Sstevel@tonic-gate * 343*7c478bd9Sstevel@tonic-gate * Calculate exactly how much space is needed in front 344*7c478bd9Sstevel@tonic-gate * of the "plaintext" in an mbuf so it can be positioned 345*7c478bd9Sstevel@tonic-gate * 1 time instead of potentially moving the data multiple 346*7c478bd9Sstevel@tonic-gate * times. 347*7c478bd9Sstevel@tonic-gate */ 348*7c478bd9Sstevel@tonic-gate static int 349*7c478bd9Sstevel@tonic-gate plaintext_offset(struct cipher_data_t *cd) 350*7c478bd9Sstevel@tonic-gate { 351*7c478bd9Sstevel@tonic-gate int headspace = 0; 352*7c478bd9Sstevel@tonic-gate 353*7c478bd9Sstevel@tonic-gate /* 4 byte length prepended to all RCMD msgs */ 354*7c478bd9Sstevel@tonic-gate if (ANY_RCMD_MODE(cd->option_mask)) 355*7c478bd9Sstevel@tonic-gate headspace += RCMD_LEN_SZ; 356*7c478bd9Sstevel@tonic-gate 357*7c478bd9Sstevel@tonic-gate /* RCMD V2 mode adds an additional 4 byte plaintext length */ 358*7c478bd9Sstevel@tonic-gate if (cd->option_mask & CRYPTOPT_RCMD_MODE_V2) 359*7c478bd9Sstevel@tonic-gate headspace += RCMD_LEN_SZ; 360*7c478bd9Sstevel@tonic-gate 361*7c478bd9Sstevel@tonic-gate /* Need extra space for hash and counfounder */ 362*7c478bd9Sstevel@tonic-gate switch (cd->method) { 363*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_DES_CBC_NULL: 364*7c478bd9Sstevel@tonic-gate headspace += null_hash.hash_len + null_hash.confound_len; 365*7c478bd9Sstevel@tonic-gate break; 366*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_DES_CBC_CRC: 367*7c478bd9Sstevel@tonic-gate headspace += crc32_hash.hash_len + crc32_hash.confound_len; 368*7c478bd9Sstevel@tonic-gate break; 369*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_DES_CBC_MD5: 370*7c478bd9Sstevel@tonic-gate headspace += md5_hash.hash_len + md5_hash.confound_len; 371*7c478bd9Sstevel@tonic-gate break; 372*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_DES3_CBC_SHA1: 373*7c478bd9Sstevel@tonic-gate headspace += sha1_hash.confound_len; 374*7c478bd9Sstevel@tonic-gate break; 375*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_ARCFOUR_HMAC_MD5: 376*7c478bd9Sstevel@tonic-gate headspace += md5_hash.hash_len + md5_hash.confound_len; 377*7c478bd9Sstevel@tonic-gate break; 378*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_AES128: 379*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_AES256: 380*7c478bd9Sstevel@tonic-gate headspace += DEFAULT_AES_BLOCKLEN; 381*7c478bd9Sstevel@tonic-gate break; 382*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_DES_CFB: 383*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_NONE: 384*7c478bd9Sstevel@tonic-gate break; 385*7c478bd9Sstevel@tonic-gate } 386*7c478bd9Sstevel@tonic-gate 387*7c478bd9Sstevel@tonic-gate return (headspace); 388*7c478bd9Sstevel@tonic-gate } 389*7c478bd9Sstevel@tonic-gate /* 390*7c478bd9Sstevel@tonic-gate * encrypt_size 391*7c478bd9Sstevel@tonic-gate * 392*7c478bd9Sstevel@tonic-gate * Calculate the resulting size when encrypting 'plainlen' bytes 393*7c478bd9Sstevel@tonic-gate * of data. 394*7c478bd9Sstevel@tonic-gate */ 395*7c478bd9Sstevel@tonic-gate static size_t 396*7c478bd9Sstevel@tonic-gate encrypt_size(struct cipher_data_t *cd, size_t plainlen) 397*7c478bd9Sstevel@tonic-gate { 398*7c478bd9Sstevel@tonic-gate size_t cipherlen; 399*7c478bd9Sstevel@tonic-gate 400*7c478bd9Sstevel@tonic-gate switch (cd->method) { 401*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_DES_CBC_NULL: 402*7c478bd9Sstevel@tonic-gate cipherlen = (size_t)P2ROUNDUP(null_hash.hash_len + 403*7c478bd9Sstevel@tonic-gate plainlen, 8); 404*7c478bd9Sstevel@tonic-gate break; 405*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_DES_CBC_MD5: 406*7c478bd9Sstevel@tonic-gate cipherlen = (size_t)P2ROUNDUP(md5_hash.hash_len + 407*7c478bd9Sstevel@tonic-gate md5_hash.confound_len + 408*7c478bd9Sstevel@tonic-gate plainlen, 8); 409*7c478bd9Sstevel@tonic-gate break; 410*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_DES_CBC_CRC: 411*7c478bd9Sstevel@tonic-gate cipherlen = (size_t)P2ROUNDUP(crc32_hash.hash_len + 412*7c478bd9Sstevel@tonic-gate crc32_hash.confound_len + 413*7c478bd9Sstevel@tonic-gate plainlen, 8); 414*7c478bd9Sstevel@tonic-gate break; 415*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_DES3_CBC_SHA1: 416*7c478bd9Sstevel@tonic-gate cipherlen = (size_t)P2ROUNDUP(sha1_hash.confound_len + 417*7c478bd9Sstevel@tonic-gate plainlen, 8) + 418*7c478bd9Sstevel@tonic-gate sha1_hash.hash_len; 419*7c478bd9Sstevel@tonic-gate break; 420*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_ARCFOUR_HMAC_MD5: 421*7c478bd9Sstevel@tonic-gate cipherlen = (size_t)P2ROUNDUP(md5_hash.confound_len + 422*7c478bd9Sstevel@tonic-gate plainlen, 1) + md5_hash.hash_len; 423*7c478bd9Sstevel@tonic-gate break; 424*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_AES128: 425*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_AES256: 426*7c478bd9Sstevel@tonic-gate /* No roundup for AES-CBC-CTS */ 427*7c478bd9Sstevel@tonic-gate cipherlen = DEFAULT_AES_BLOCKLEN + plainlen + 428*7c478bd9Sstevel@tonic-gate AES_TRUNCATED_HMAC_LEN; 429*7c478bd9Sstevel@tonic-gate break; 430*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_DES_CFB: 431*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_NONE: 432*7c478bd9Sstevel@tonic-gate cipherlen = plainlen; 433*7c478bd9Sstevel@tonic-gate break; 434*7c478bd9Sstevel@tonic-gate } 435*7c478bd9Sstevel@tonic-gate 436*7c478bd9Sstevel@tonic-gate return (cipherlen); 437*7c478bd9Sstevel@tonic-gate } 438*7c478bd9Sstevel@tonic-gate 439*7c478bd9Sstevel@tonic-gate /* 440*7c478bd9Sstevel@tonic-gate * des_cfb_encrypt 441*7c478bd9Sstevel@tonic-gate * 442*7c478bd9Sstevel@tonic-gate * Encrypt the mblk data using DES with cipher feedback. 443*7c478bd9Sstevel@tonic-gate * 444*7c478bd9Sstevel@tonic-gate * Given that V[i] is the initial 64 bit vector, V[n] is the nth 64 bit 445*7c478bd9Sstevel@tonic-gate * vector, D[n] is the nth chunk of 64 bits of data to encrypt 446*7c478bd9Sstevel@tonic-gate * (decrypt), and O[n] is the nth chunk of 64 bits of encrypted 447*7c478bd9Sstevel@tonic-gate * (decrypted) data, then: 448*7c478bd9Sstevel@tonic-gate * 449*7c478bd9Sstevel@tonic-gate * V[0] = DES(V[i], key) 450*7c478bd9Sstevel@tonic-gate * O[n] = D[n] <exclusive or > V[n] 451*7c478bd9Sstevel@tonic-gate * V[n+1] = DES(O[n], key) 452*7c478bd9Sstevel@tonic-gate * 453*7c478bd9Sstevel@tonic-gate * The size of the message being encrypted does not change in this 454*7c478bd9Sstevel@tonic-gate * algorithm, num_bytes in == num_bytes out. 455*7c478bd9Sstevel@tonic-gate */ 456*7c478bd9Sstevel@tonic-gate static mblk_t * 457*7c478bd9Sstevel@tonic-gate des_cfb_encrypt(queue_t *q, struct tmodinfo *tmi, mblk_t *mp) 458*7c478bd9Sstevel@tonic-gate { 459*7c478bd9Sstevel@tonic-gate int savedbytes; 460*7c478bd9Sstevel@tonic-gate char *iptr, *optr, *lastoutput; 461*7c478bd9Sstevel@tonic-gate 462*7c478bd9Sstevel@tonic-gate lastoutput = optr = (char *)mp->b_rptr; 463*7c478bd9Sstevel@tonic-gate iptr = (char *)mp->b_rptr; 464*7c478bd9Sstevel@tonic-gate savedbytes = tmi->enc_data.bytes % CFB_BLKSZ; 465*7c478bd9Sstevel@tonic-gate 466*7c478bd9Sstevel@tonic-gate while (iptr < (char *)mp->b_wptr) { 467*7c478bd9Sstevel@tonic-gate /* 468*7c478bd9Sstevel@tonic-gate * Do DES-ECB. 469*7c478bd9Sstevel@tonic-gate * The first time this runs, the 'tmi->enc_data.block' will 470*7c478bd9Sstevel@tonic-gate * contain the initialization vector that should have been 471*7c478bd9Sstevel@tonic-gate * passed in with the SETUP ioctl. 472*7c478bd9Sstevel@tonic-gate * 473*7c478bd9Sstevel@tonic-gate * V[n] = DES(V[n-1], key) 474*7c478bd9Sstevel@tonic-gate */ 475*7c478bd9Sstevel@tonic-gate if (!(tmi->enc_data.bytes % CFB_BLKSZ)) { 476*7c478bd9Sstevel@tonic-gate int retval = 0; 477*7c478bd9Sstevel@tonic-gate retval = kef_crypt(&tmi->enc_data, 478*7c478bd9Sstevel@tonic-gate tmi->enc_data.block, 479*7c478bd9Sstevel@tonic-gate CRYPTO_DATA_RAW, 480*7c478bd9Sstevel@tonic-gate tmi->enc_data.blocklen, 481*7c478bd9Sstevel@tonic-gate CRYPT_ENCRYPT); 482*7c478bd9Sstevel@tonic-gate 483*7c478bd9Sstevel@tonic-gate if (retval != CRYPTO_SUCCESS) { 484*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 485*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "des_cfb_encrypt: kef_crypt " 486*7c478bd9Sstevel@tonic-gate "failed - error 0x%0x", retval); 487*7c478bd9Sstevel@tonic-gate #endif 488*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_ERROR; 489*7c478bd9Sstevel@tonic-gate mp->b_rptr = mp->b_datap->db_base; 490*7c478bd9Sstevel@tonic-gate *mp->b_rptr = EIO; 491*7c478bd9Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + sizeof (char); 492*7c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 493*7c478bd9Sstevel@tonic-gate mp->b_cont = NULL; 494*7c478bd9Sstevel@tonic-gate qreply(WR(q), mp); 495*7c478bd9Sstevel@tonic-gate return (NULL); 496*7c478bd9Sstevel@tonic-gate } 497*7c478bd9Sstevel@tonic-gate } 498*7c478bd9Sstevel@tonic-gate 499*7c478bd9Sstevel@tonic-gate /* O[n] = I[n] ^ V[n] */ 500*7c478bd9Sstevel@tonic-gate *(optr++) = *(iptr++) ^ 501*7c478bd9Sstevel@tonic-gate tmi->enc_data.block[tmi->enc_data.bytes % CFB_BLKSZ]; 502*7c478bd9Sstevel@tonic-gate 503*7c478bd9Sstevel@tonic-gate tmi->enc_data.bytes++; 504*7c478bd9Sstevel@tonic-gate /* 505*7c478bd9Sstevel@tonic-gate * Feedback the encrypted output as the input to next DES call. 506*7c478bd9Sstevel@tonic-gate */ 507*7c478bd9Sstevel@tonic-gate if (!(tmi->enc_data.bytes % CFB_BLKSZ)) { 508*7c478bd9Sstevel@tonic-gate char *dbptr = tmi->enc_data.block; 509*7c478bd9Sstevel@tonic-gate /* 510*7c478bd9Sstevel@tonic-gate * Get the last bits of input from the previous 511*7c478bd9Sstevel@tonic-gate * msg block that we haven't yet used as feedback input. 512*7c478bd9Sstevel@tonic-gate */ 513*7c478bd9Sstevel@tonic-gate if (savedbytes > 0) { 514*7c478bd9Sstevel@tonic-gate bcopy(tmi->enc_data.saveblock, 515*7c478bd9Sstevel@tonic-gate dbptr, (size_t)savedbytes); 516*7c478bd9Sstevel@tonic-gate dbptr += savedbytes; 517*7c478bd9Sstevel@tonic-gate } 518*7c478bd9Sstevel@tonic-gate 519*7c478bd9Sstevel@tonic-gate /* 520*7c478bd9Sstevel@tonic-gate * Now copy the correct bytes from the current input 521*7c478bd9Sstevel@tonic-gate * stream and update the 'lastoutput' ptr 522*7c478bd9Sstevel@tonic-gate */ 523*7c478bd9Sstevel@tonic-gate bcopy(lastoutput, dbptr, 524*7c478bd9Sstevel@tonic-gate (size_t)(CFB_BLKSZ - savedbytes)); 525*7c478bd9Sstevel@tonic-gate 526*7c478bd9Sstevel@tonic-gate lastoutput += (CFB_BLKSZ - savedbytes); 527*7c478bd9Sstevel@tonic-gate savedbytes = 0; 528*7c478bd9Sstevel@tonic-gate } 529*7c478bd9Sstevel@tonic-gate } 530*7c478bd9Sstevel@tonic-gate /* 531*7c478bd9Sstevel@tonic-gate * If there are bytes of input here that we need in the next 532*7c478bd9Sstevel@tonic-gate * block to build an ivec, save them off here. 533*7c478bd9Sstevel@tonic-gate */ 534*7c478bd9Sstevel@tonic-gate if (lastoutput < optr) { 535*7c478bd9Sstevel@tonic-gate bcopy(lastoutput, 536*7c478bd9Sstevel@tonic-gate tmi->enc_data.saveblock + savedbytes, 537*7c478bd9Sstevel@tonic-gate (uint_t)(optr - lastoutput)); 538*7c478bd9Sstevel@tonic-gate } 539*7c478bd9Sstevel@tonic-gate return (mp); 540*7c478bd9Sstevel@tonic-gate } 541*7c478bd9Sstevel@tonic-gate 542*7c478bd9Sstevel@tonic-gate /* 543*7c478bd9Sstevel@tonic-gate * des_cfb_decrypt 544*7c478bd9Sstevel@tonic-gate * 545*7c478bd9Sstevel@tonic-gate * Decrypt the data in the mblk using DES in Cipher Feedback mode 546*7c478bd9Sstevel@tonic-gate * 547*7c478bd9Sstevel@tonic-gate * # bytes in == # bytes out, no padding, confounding, or hashing 548*7c478bd9Sstevel@tonic-gate * is added. 549*7c478bd9Sstevel@tonic-gate * 550*7c478bd9Sstevel@tonic-gate */ 551*7c478bd9Sstevel@tonic-gate static mblk_t * 552*7c478bd9Sstevel@tonic-gate des_cfb_decrypt(queue_t *q, struct tmodinfo *tmi, mblk_t *mp) 553*7c478bd9Sstevel@tonic-gate { 554*7c478bd9Sstevel@tonic-gate uint_t len; 555*7c478bd9Sstevel@tonic-gate uint_t savedbytes; 556*7c478bd9Sstevel@tonic-gate char *iptr; 557*7c478bd9Sstevel@tonic-gate char *lastinput; 558*7c478bd9Sstevel@tonic-gate uint_t cp; 559*7c478bd9Sstevel@tonic-gate 560*7c478bd9Sstevel@tonic-gate len = MBLKL(mp); 561*7c478bd9Sstevel@tonic-gate 562*7c478bd9Sstevel@tonic-gate /* decrypted output goes into the new data buffer */ 563*7c478bd9Sstevel@tonic-gate lastinput = iptr = (char *)mp->b_rptr; 564*7c478bd9Sstevel@tonic-gate 565*7c478bd9Sstevel@tonic-gate savedbytes = tmi->dec_data.bytes % tmi->dec_data.blocklen; 566*7c478bd9Sstevel@tonic-gate 567*7c478bd9Sstevel@tonic-gate /* 568*7c478bd9Sstevel@tonic-gate * Save the input CFB_BLKSZ bytes at a time. 569*7c478bd9Sstevel@tonic-gate * We are trying to decrypt in-place, but need to keep 570*7c478bd9Sstevel@tonic-gate * a small sliding window of encrypted text to be 571*7c478bd9Sstevel@tonic-gate * used to construct the feedback buffer. 572*7c478bd9Sstevel@tonic-gate */ 573*7c478bd9Sstevel@tonic-gate cp = ((tmi->dec_data.blocklen - savedbytes) > len ? len : 574*7c478bd9Sstevel@tonic-gate tmi->dec_data.blocklen - savedbytes); 575*7c478bd9Sstevel@tonic-gate 576*7c478bd9Sstevel@tonic-gate bcopy(lastinput, tmi->dec_data.saveblock + savedbytes, cp); 577*7c478bd9Sstevel@tonic-gate savedbytes += cp; 578*7c478bd9Sstevel@tonic-gate 579*7c478bd9Sstevel@tonic-gate lastinput += cp; 580*7c478bd9Sstevel@tonic-gate 581*7c478bd9Sstevel@tonic-gate while (iptr < (char *)mp->b_wptr) { 582*7c478bd9Sstevel@tonic-gate /* 583*7c478bd9Sstevel@tonic-gate * Do DES-ECB. 584*7c478bd9Sstevel@tonic-gate * The first time this runs, the 'tmi->dec_data.block' will 585*7c478bd9Sstevel@tonic-gate * contain the initialization vector that should have been 586*7c478bd9Sstevel@tonic-gate * passed in with the SETUP ioctl. 587*7c478bd9Sstevel@tonic-gate */ 588*7c478bd9Sstevel@tonic-gate if (!(tmi->dec_data.bytes % CFB_BLKSZ)) { 589*7c478bd9Sstevel@tonic-gate int retval; 590*7c478bd9Sstevel@tonic-gate retval = kef_crypt(&tmi->dec_data, 591*7c478bd9Sstevel@tonic-gate tmi->dec_data.block, 592*7c478bd9Sstevel@tonic-gate CRYPTO_DATA_RAW, 593*7c478bd9Sstevel@tonic-gate tmi->dec_data.blocklen, 594*7c478bd9Sstevel@tonic-gate CRYPT_ENCRYPT); 595*7c478bd9Sstevel@tonic-gate 596*7c478bd9Sstevel@tonic-gate if (retval != CRYPTO_SUCCESS) { 597*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 598*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "des_cfb_decrypt: kef_crypt " 599*7c478bd9Sstevel@tonic-gate "failed - status 0x%0x", retval); 600*7c478bd9Sstevel@tonic-gate #endif 601*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_ERROR; 602*7c478bd9Sstevel@tonic-gate mp->b_rptr = mp->b_datap->db_base; 603*7c478bd9Sstevel@tonic-gate *mp->b_rptr = EIO; 604*7c478bd9Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + sizeof (char); 605*7c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 606*7c478bd9Sstevel@tonic-gate mp->b_cont = NULL; 607*7c478bd9Sstevel@tonic-gate qreply(WR(q), mp); 608*7c478bd9Sstevel@tonic-gate return (NULL); 609*7c478bd9Sstevel@tonic-gate } 610*7c478bd9Sstevel@tonic-gate } 611*7c478bd9Sstevel@tonic-gate 612*7c478bd9Sstevel@tonic-gate /* 613*7c478bd9Sstevel@tonic-gate * To decrypt, XOR the input with the output from the DES call 614*7c478bd9Sstevel@tonic-gate */ 615*7c478bd9Sstevel@tonic-gate *(iptr++) ^= tmi->dec_data.block[tmi->dec_data.bytes % 616*7c478bd9Sstevel@tonic-gate CFB_BLKSZ]; 617*7c478bd9Sstevel@tonic-gate 618*7c478bd9Sstevel@tonic-gate tmi->dec_data.bytes++; 619*7c478bd9Sstevel@tonic-gate 620*7c478bd9Sstevel@tonic-gate /* 621*7c478bd9Sstevel@tonic-gate * Feedback the encrypted input for next DES call. 622*7c478bd9Sstevel@tonic-gate */ 623*7c478bd9Sstevel@tonic-gate if (!(tmi->dec_data.bytes % tmi->dec_data.blocklen)) { 624*7c478bd9Sstevel@tonic-gate char *dbptr = tmi->dec_data.block; 625*7c478bd9Sstevel@tonic-gate /* 626*7c478bd9Sstevel@tonic-gate * Get the last bits of input from the previous block 627*7c478bd9Sstevel@tonic-gate * that we haven't yet processed. 628*7c478bd9Sstevel@tonic-gate */ 629*7c478bd9Sstevel@tonic-gate if (savedbytes > 0) { 630*7c478bd9Sstevel@tonic-gate bcopy(tmi->dec_data.saveblock, 631*7c478bd9Sstevel@tonic-gate dbptr, savedbytes); 632*7c478bd9Sstevel@tonic-gate dbptr += savedbytes; 633*7c478bd9Sstevel@tonic-gate } 634*7c478bd9Sstevel@tonic-gate 635*7c478bd9Sstevel@tonic-gate savedbytes = 0; 636*7c478bd9Sstevel@tonic-gate 637*7c478bd9Sstevel@tonic-gate /* 638*7c478bd9Sstevel@tonic-gate * This block makes sure that our local 639*7c478bd9Sstevel@tonic-gate * buffer of input data is full and can 640*7c478bd9Sstevel@tonic-gate * be accessed from the beginning. 641*7c478bd9Sstevel@tonic-gate */ 642*7c478bd9Sstevel@tonic-gate if (lastinput < (char *)mp->b_wptr) { 643*7c478bd9Sstevel@tonic-gate 644*7c478bd9Sstevel@tonic-gate /* How many bytes are left in the mblk? */ 645*7c478bd9Sstevel@tonic-gate cp = (((char *)mp->b_wptr - lastinput) > 646*7c478bd9Sstevel@tonic-gate tmi->dec_data.blocklen ? 647*7c478bd9Sstevel@tonic-gate tmi->dec_data.blocklen : 648*7c478bd9Sstevel@tonic-gate (char *)mp->b_wptr - lastinput); 649*7c478bd9Sstevel@tonic-gate 650*7c478bd9Sstevel@tonic-gate /* copy what we need */ 651*7c478bd9Sstevel@tonic-gate bcopy(lastinput, tmi->dec_data.saveblock, 652*7c478bd9Sstevel@tonic-gate cp); 653*7c478bd9Sstevel@tonic-gate 654*7c478bd9Sstevel@tonic-gate lastinput += cp; 655*7c478bd9Sstevel@tonic-gate savedbytes = cp; 656*7c478bd9Sstevel@tonic-gate } 657*7c478bd9Sstevel@tonic-gate } 658*7c478bd9Sstevel@tonic-gate } 659*7c478bd9Sstevel@tonic-gate 660*7c478bd9Sstevel@tonic-gate return (mp); 661*7c478bd9Sstevel@tonic-gate } 662*7c478bd9Sstevel@tonic-gate 663*7c478bd9Sstevel@tonic-gate /* 664*7c478bd9Sstevel@tonic-gate * crc32_calc 665*7c478bd9Sstevel@tonic-gate * 666*7c478bd9Sstevel@tonic-gate * Compute a CRC32 checksum on the input 667*7c478bd9Sstevel@tonic-gate */ 668*7c478bd9Sstevel@tonic-gate static int 669*7c478bd9Sstevel@tonic-gate crc32_calc(uchar_t *buf, uchar_t *input, uint_t len) 670*7c478bd9Sstevel@tonic-gate { 671*7c478bd9Sstevel@tonic-gate uint32_t crc; 672*7c478bd9Sstevel@tonic-gate 673*7c478bd9Sstevel@tonic-gate CRC32(crc, input, len, 0, crc32_table); 674*7c478bd9Sstevel@tonic-gate 675*7c478bd9Sstevel@tonic-gate buf[0] = (uchar_t)(crc & 0xff); 676*7c478bd9Sstevel@tonic-gate buf[1] = (uchar_t)((crc >> 8) & 0xff); 677*7c478bd9Sstevel@tonic-gate buf[2] = (uchar_t)((crc >> 16) & 0xff); 678*7c478bd9Sstevel@tonic-gate buf[3] = (uchar_t)((crc >> 24) & 0xff); 679*7c478bd9Sstevel@tonic-gate 680*7c478bd9Sstevel@tonic-gate return (CRYPTO_SUCCESS); 681*7c478bd9Sstevel@tonic-gate } 682*7c478bd9Sstevel@tonic-gate 683*7c478bd9Sstevel@tonic-gate static int 684*7c478bd9Sstevel@tonic-gate kef_digest(crypto_mech_type_t digest_type, 685*7c478bd9Sstevel@tonic-gate uchar_t *input, uint_t inlen, 686*7c478bd9Sstevel@tonic-gate uchar_t *output, uint_t hashlen) 687*7c478bd9Sstevel@tonic-gate { 688*7c478bd9Sstevel@tonic-gate iovec_t v1, v2; 689*7c478bd9Sstevel@tonic-gate crypto_data_t d1, d2; 690*7c478bd9Sstevel@tonic-gate crypto_mechanism_t mech; 691*7c478bd9Sstevel@tonic-gate int rv; 692*7c478bd9Sstevel@tonic-gate 693*7c478bd9Sstevel@tonic-gate mech.cm_type = digest_type; 694*7c478bd9Sstevel@tonic-gate mech.cm_param = 0; 695*7c478bd9Sstevel@tonic-gate mech.cm_param_len = 0; 696*7c478bd9Sstevel@tonic-gate 697*7c478bd9Sstevel@tonic-gate v1.iov_base = (void *)input; 698*7c478bd9Sstevel@tonic-gate v1.iov_len = inlen; 699*7c478bd9Sstevel@tonic-gate 700*7c478bd9Sstevel@tonic-gate d1.cd_format = CRYPTO_DATA_RAW; 701*7c478bd9Sstevel@tonic-gate d1.cd_offset = 0; 702*7c478bd9Sstevel@tonic-gate d1.cd_length = v1.iov_len; 703*7c478bd9Sstevel@tonic-gate d1.cd_raw = v1; 704*7c478bd9Sstevel@tonic-gate 705*7c478bd9Sstevel@tonic-gate v2.iov_base = (void *)output; 706*7c478bd9Sstevel@tonic-gate v2.iov_len = hashlen; 707*7c478bd9Sstevel@tonic-gate 708*7c478bd9Sstevel@tonic-gate d2.cd_format = CRYPTO_DATA_RAW; 709*7c478bd9Sstevel@tonic-gate d2.cd_offset = 0; 710*7c478bd9Sstevel@tonic-gate d2.cd_length = v2.iov_len; 711*7c478bd9Sstevel@tonic-gate d2.cd_raw = v2; 712*7c478bd9Sstevel@tonic-gate 713*7c478bd9Sstevel@tonic-gate rv = crypto_digest(&mech, &d1, &d2, NULL); 714*7c478bd9Sstevel@tonic-gate 715*7c478bd9Sstevel@tonic-gate return (rv); 716*7c478bd9Sstevel@tonic-gate } 717*7c478bd9Sstevel@tonic-gate 718*7c478bd9Sstevel@tonic-gate /* 719*7c478bd9Sstevel@tonic-gate * sha1_calc 720*7c478bd9Sstevel@tonic-gate * 721*7c478bd9Sstevel@tonic-gate * Get a SHA1 hash on the input data. 722*7c478bd9Sstevel@tonic-gate */ 723*7c478bd9Sstevel@tonic-gate static int 724*7c478bd9Sstevel@tonic-gate sha1_calc(uchar_t *output, uchar_t *input, uint_t inlen) 725*7c478bd9Sstevel@tonic-gate { 726*7c478bd9Sstevel@tonic-gate int rv; 727*7c478bd9Sstevel@tonic-gate 728*7c478bd9Sstevel@tonic-gate rv = kef_digest(sha1_hash_mech, input, inlen, output, SHA1_HASHSIZE); 729*7c478bd9Sstevel@tonic-gate 730*7c478bd9Sstevel@tonic-gate return (rv); 731*7c478bd9Sstevel@tonic-gate } 732*7c478bd9Sstevel@tonic-gate 733*7c478bd9Sstevel@tonic-gate /* 734*7c478bd9Sstevel@tonic-gate * Get an MD5 hash on the input data. 735*7c478bd9Sstevel@tonic-gate * md5_calc 736*7c478bd9Sstevel@tonic-gate * 737*7c478bd9Sstevel@tonic-gate */ 738*7c478bd9Sstevel@tonic-gate static int 739*7c478bd9Sstevel@tonic-gate md5_calc(uchar_t *output, uchar_t *input, uint_t inlen) 740*7c478bd9Sstevel@tonic-gate { 741*7c478bd9Sstevel@tonic-gate int rv; 742*7c478bd9Sstevel@tonic-gate 743*7c478bd9Sstevel@tonic-gate rv = kef_digest(md5_hash_mech, input, inlen, output, MD5_HASHSIZE); 744*7c478bd9Sstevel@tonic-gate 745*7c478bd9Sstevel@tonic-gate return (rv); 746*7c478bd9Sstevel@tonic-gate } 747*7c478bd9Sstevel@tonic-gate 748*7c478bd9Sstevel@tonic-gate /* 749*7c478bd9Sstevel@tonic-gate * nfold 750*7c478bd9Sstevel@tonic-gate * duplicate the functionality of the krb5_nfold function from 751*7c478bd9Sstevel@tonic-gate * the userland kerberos mech. 752*7c478bd9Sstevel@tonic-gate * This is needed to derive keys for use with 3DES/SHA1-HMAC 753*7c478bd9Sstevel@tonic-gate * ciphers. 754*7c478bd9Sstevel@tonic-gate */ 755*7c478bd9Sstevel@tonic-gate static void 756*7c478bd9Sstevel@tonic-gate nfold(int inbits, uchar_t *in, int outbits, uchar_t *out) 757*7c478bd9Sstevel@tonic-gate { 758*7c478bd9Sstevel@tonic-gate int a, b, c, lcm; 759*7c478bd9Sstevel@tonic-gate int byte, i, msbit; 760*7c478bd9Sstevel@tonic-gate 761*7c478bd9Sstevel@tonic-gate inbits >>= 3; 762*7c478bd9Sstevel@tonic-gate outbits >>= 3; 763*7c478bd9Sstevel@tonic-gate 764*7c478bd9Sstevel@tonic-gate /* first compute lcm(n,k) */ 765*7c478bd9Sstevel@tonic-gate a = outbits; 766*7c478bd9Sstevel@tonic-gate b = inbits; 767*7c478bd9Sstevel@tonic-gate 768*7c478bd9Sstevel@tonic-gate while (b != 0) { 769*7c478bd9Sstevel@tonic-gate c = b; 770*7c478bd9Sstevel@tonic-gate b = a%b; 771*7c478bd9Sstevel@tonic-gate a = c; 772*7c478bd9Sstevel@tonic-gate } 773*7c478bd9Sstevel@tonic-gate 774*7c478bd9Sstevel@tonic-gate lcm = outbits*inbits/a; 775*7c478bd9Sstevel@tonic-gate 776*7c478bd9Sstevel@tonic-gate /* now do the real work */ 777*7c478bd9Sstevel@tonic-gate 778*7c478bd9Sstevel@tonic-gate bzero(out, outbits); 779*7c478bd9Sstevel@tonic-gate byte = 0; 780*7c478bd9Sstevel@tonic-gate 781*7c478bd9Sstevel@tonic-gate /* 782*7c478bd9Sstevel@tonic-gate * Compute the msbit in k which gets added into this byte 783*7c478bd9Sstevel@tonic-gate * first, start with the msbit in the first, unrotated byte 784*7c478bd9Sstevel@tonic-gate * then, for each byte, shift to the right for each repetition 785*7c478bd9Sstevel@tonic-gate * last, pick out the correct byte within that shifted repetition 786*7c478bd9Sstevel@tonic-gate */ 787*7c478bd9Sstevel@tonic-gate for (i = lcm-1; i >= 0; i--) { 788*7c478bd9Sstevel@tonic-gate msbit = (((inbits<<3)-1) 789*7c478bd9Sstevel@tonic-gate +(((inbits<<3)+13)*(i/inbits)) 790*7c478bd9Sstevel@tonic-gate +((inbits-(i%inbits))<<3)) %(inbits<<3); 791*7c478bd9Sstevel@tonic-gate 792*7c478bd9Sstevel@tonic-gate /* pull out the byte value itself */ 793*7c478bd9Sstevel@tonic-gate byte += (((in[((inbits-1)-(msbit>>3))%inbits]<<8)| 794*7c478bd9Sstevel@tonic-gate (in[((inbits)-(msbit>>3))%inbits])) 795*7c478bd9Sstevel@tonic-gate >>((msbit&7)+1))&0xff; 796*7c478bd9Sstevel@tonic-gate 797*7c478bd9Sstevel@tonic-gate /* do the addition */ 798*7c478bd9Sstevel@tonic-gate byte += out[i%outbits]; 799*7c478bd9Sstevel@tonic-gate out[i%outbits] = byte&0xff; 800*7c478bd9Sstevel@tonic-gate 801*7c478bd9Sstevel@tonic-gate byte >>= 8; 802*7c478bd9Sstevel@tonic-gate } 803*7c478bd9Sstevel@tonic-gate 804*7c478bd9Sstevel@tonic-gate /* if there's a carry bit left over, add it back in */ 805*7c478bd9Sstevel@tonic-gate if (byte) { 806*7c478bd9Sstevel@tonic-gate for (i = outbits-1; i >= 0; i--) { 807*7c478bd9Sstevel@tonic-gate /* do the addition */ 808*7c478bd9Sstevel@tonic-gate byte += out[i]; 809*7c478bd9Sstevel@tonic-gate out[i] = byte&0xff; 810*7c478bd9Sstevel@tonic-gate 811*7c478bd9Sstevel@tonic-gate /* keep around the carry bit, if any */ 812*7c478bd9Sstevel@tonic-gate byte >>= 8; 813*7c478bd9Sstevel@tonic-gate } 814*7c478bd9Sstevel@tonic-gate } 815*7c478bd9Sstevel@tonic-gate } 816*7c478bd9Sstevel@tonic-gate 817*7c478bd9Sstevel@tonic-gate #define smask(step) ((1<<step)-1) 818*7c478bd9Sstevel@tonic-gate #define pstep(x, step) (((x)&smask(step))^(((x)>>step)&smask(step))) 819*7c478bd9Sstevel@tonic-gate #define parity_char(x) pstep(pstep(pstep((x), 4), 2), 1) 820*7c478bd9Sstevel@tonic-gate 821*7c478bd9Sstevel@tonic-gate /* 822*7c478bd9Sstevel@tonic-gate * Duplicate the functionality of the "dk_derive_key" function 823*7c478bd9Sstevel@tonic-gate * in the Kerberos mechanism. 824*7c478bd9Sstevel@tonic-gate */ 825*7c478bd9Sstevel@tonic-gate static int 826*7c478bd9Sstevel@tonic-gate derive_key(struct cipher_data_t *cdata, uchar_t *constdata, 827*7c478bd9Sstevel@tonic-gate int constlen, char *dkey, int keybytes, 828*7c478bd9Sstevel@tonic-gate int blocklen) 829*7c478bd9Sstevel@tonic-gate { 830*7c478bd9Sstevel@tonic-gate int rv = 0; 831*7c478bd9Sstevel@tonic-gate int n = 0, i; 832*7c478bd9Sstevel@tonic-gate char *inblock; 833*7c478bd9Sstevel@tonic-gate char *rawkey; 834*7c478bd9Sstevel@tonic-gate char *zeroblock; 835*7c478bd9Sstevel@tonic-gate char *saveblock; 836*7c478bd9Sstevel@tonic-gate 837*7c478bd9Sstevel@tonic-gate inblock = kmem_zalloc(blocklen, KM_SLEEP); 838*7c478bd9Sstevel@tonic-gate rawkey = kmem_zalloc(keybytes, KM_SLEEP); 839*7c478bd9Sstevel@tonic-gate zeroblock = kmem_zalloc(blocklen, KM_SLEEP); 840*7c478bd9Sstevel@tonic-gate 841*7c478bd9Sstevel@tonic-gate if (constlen == blocklen) 842*7c478bd9Sstevel@tonic-gate bcopy(constdata, inblock, blocklen); 843*7c478bd9Sstevel@tonic-gate else 844*7c478bd9Sstevel@tonic-gate nfold(constlen * 8, constdata, 845*7c478bd9Sstevel@tonic-gate blocklen * 8, (uchar_t *)inblock); 846*7c478bd9Sstevel@tonic-gate 847*7c478bd9Sstevel@tonic-gate /* 848*7c478bd9Sstevel@tonic-gate * zeroblock is an IV of all 0's. 849*7c478bd9Sstevel@tonic-gate * 850*7c478bd9Sstevel@tonic-gate * The "block" section of the cdata record is used as the 851*7c478bd9Sstevel@tonic-gate * IV for crypto operations in the kef_crypt function. 852*7c478bd9Sstevel@tonic-gate * 853*7c478bd9Sstevel@tonic-gate * We use 'block' as a generic IV data buffer because it 854*7c478bd9Sstevel@tonic-gate * is attached to the stream state data and thus can 855*7c478bd9Sstevel@tonic-gate * be used to hold information that must carry over 856*7c478bd9Sstevel@tonic-gate * from processing of one mblk to another. 857*7c478bd9Sstevel@tonic-gate * 858*7c478bd9Sstevel@tonic-gate * Here, we save the current IV and replace it with 859*7c478bd9Sstevel@tonic-gate * and empty IV (all 0's) for use when deriving the 860*7c478bd9Sstevel@tonic-gate * keys. Once the key derivation is done, we swap the 861*7c478bd9Sstevel@tonic-gate * old IV back into place. 862*7c478bd9Sstevel@tonic-gate */ 863*7c478bd9Sstevel@tonic-gate saveblock = cdata->block; 864*7c478bd9Sstevel@tonic-gate cdata->block = zeroblock; 865*7c478bd9Sstevel@tonic-gate 866*7c478bd9Sstevel@tonic-gate while (n < keybytes) { 867*7c478bd9Sstevel@tonic-gate rv = kef_crypt(cdata, inblock, CRYPTO_DATA_RAW, 868*7c478bd9Sstevel@tonic-gate blocklen, CRYPT_ENCRYPT); 869*7c478bd9Sstevel@tonic-gate if (rv != CRYPTO_SUCCESS) { 870*7c478bd9Sstevel@tonic-gate /* put the original IV block back in place */ 871*7c478bd9Sstevel@tonic-gate cdata->block = saveblock; 872*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "failed to derive a key: %0x", rv); 873*7c478bd9Sstevel@tonic-gate goto cleanup; 874*7c478bd9Sstevel@tonic-gate } 875*7c478bd9Sstevel@tonic-gate 876*7c478bd9Sstevel@tonic-gate if (keybytes - n < blocklen) { 877*7c478bd9Sstevel@tonic-gate bcopy(inblock, rawkey+n, (keybytes-n)); 878*7c478bd9Sstevel@tonic-gate break; 879*7c478bd9Sstevel@tonic-gate } 880*7c478bd9Sstevel@tonic-gate bcopy(inblock, rawkey+n, blocklen); 881*7c478bd9Sstevel@tonic-gate n += blocklen; 882*7c478bd9Sstevel@tonic-gate } 883*7c478bd9Sstevel@tonic-gate /* put the original IV block back in place */ 884*7c478bd9Sstevel@tonic-gate cdata->block = saveblock; 885*7c478bd9Sstevel@tonic-gate 886*7c478bd9Sstevel@tonic-gate /* finally, make the key */ 887*7c478bd9Sstevel@tonic-gate if (cdata->method == CRYPT_METHOD_DES3_CBC_SHA1) { 888*7c478bd9Sstevel@tonic-gate /* 889*7c478bd9Sstevel@tonic-gate * 3DES key derivation requires that we make sure the 890*7c478bd9Sstevel@tonic-gate * key has the proper parity. 891*7c478bd9Sstevel@tonic-gate */ 892*7c478bd9Sstevel@tonic-gate for (i = 0; i < 3; i++) { 893*7c478bd9Sstevel@tonic-gate bcopy(rawkey+(i*7), dkey+(i*8), 7); 894*7c478bd9Sstevel@tonic-gate 895*7c478bd9Sstevel@tonic-gate /* 'dkey' is our derived key output buffer */ 896*7c478bd9Sstevel@tonic-gate dkey[i*8+7] = (((dkey[i*8]&1)<<1) | 897*7c478bd9Sstevel@tonic-gate ((dkey[i*8+1]&1)<<2) | 898*7c478bd9Sstevel@tonic-gate ((dkey[i*8+2]&1)<<3) | 899*7c478bd9Sstevel@tonic-gate ((dkey[i*8+3]&1)<<4) | 900*7c478bd9Sstevel@tonic-gate ((dkey[i*8+4]&1)<<5) | 901*7c478bd9Sstevel@tonic-gate ((dkey[i*8+5]&1)<<6) | 902*7c478bd9Sstevel@tonic-gate ((dkey[i*8+6]&1)<<7)); 903*7c478bd9Sstevel@tonic-gate 904*7c478bd9Sstevel@tonic-gate for (n = 0; n < 8; n++) { 905*7c478bd9Sstevel@tonic-gate dkey[i*8 + n] &= 0xfe; 906*7c478bd9Sstevel@tonic-gate dkey[i*8 + n] |= 1^parity_char(dkey[i*8 + n]); 907*7c478bd9Sstevel@tonic-gate } 908*7c478bd9Sstevel@tonic-gate } 909*7c478bd9Sstevel@tonic-gate } else if (IS_AES_METHOD(cdata->method)) { 910*7c478bd9Sstevel@tonic-gate bcopy(rawkey, dkey, keybytes); 911*7c478bd9Sstevel@tonic-gate } 912*7c478bd9Sstevel@tonic-gate cleanup: 913*7c478bd9Sstevel@tonic-gate kmem_free(inblock, blocklen); 914*7c478bd9Sstevel@tonic-gate kmem_free(zeroblock, blocklen); 915*7c478bd9Sstevel@tonic-gate kmem_free(rawkey, keybytes); 916*7c478bd9Sstevel@tonic-gate return (rv); 917*7c478bd9Sstevel@tonic-gate } 918*7c478bd9Sstevel@tonic-gate 919*7c478bd9Sstevel@tonic-gate /* 920*7c478bd9Sstevel@tonic-gate * create_derived_keys 921*7c478bd9Sstevel@tonic-gate * 922*7c478bd9Sstevel@tonic-gate * Algorithm for deriving a new key and an HMAC key 923*7c478bd9Sstevel@tonic-gate * before computing the 3DES-SHA1-HMAC operation on the plaintext 924*7c478bd9Sstevel@tonic-gate * This algorithm matches the work done by Kerberos mechanism 925*7c478bd9Sstevel@tonic-gate * in userland. 926*7c478bd9Sstevel@tonic-gate */ 927*7c478bd9Sstevel@tonic-gate static int 928*7c478bd9Sstevel@tonic-gate create_derived_keys(struct cipher_data_t *cdata, uint32_t usage, 929*7c478bd9Sstevel@tonic-gate crypto_key_t *enckey, crypto_key_t *hmackey) 930*7c478bd9Sstevel@tonic-gate { 931*7c478bd9Sstevel@tonic-gate uchar_t constdata[K5CLENGTH]; 932*7c478bd9Sstevel@tonic-gate int keybytes; 933*7c478bd9Sstevel@tonic-gate int rv; 934*7c478bd9Sstevel@tonic-gate 935*7c478bd9Sstevel@tonic-gate constdata[0] = (usage>>24)&0xff; 936*7c478bd9Sstevel@tonic-gate constdata[1] = (usage>>16)&0xff; 937*7c478bd9Sstevel@tonic-gate constdata[2] = (usage>>8)&0xff; 938*7c478bd9Sstevel@tonic-gate constdata[3] = usage & 0xff; 939*7c478bd9Sstevel@tonic-gate /* Use "0xAA" for deriving encryption key */ 940*7c478bd9Sstevel@tonic-gate constdata[4] = 0xAA; /* from MIT Kerberos code */ 941*7c478bd9Sstevel@tonic-gate 942*7c478bd9Sstevel@tonic-gate enckey->ck_length = cdata->keylen * 8; 943*7c478bd9Sstevel@tonic-gate enckey->ck_format = CRYPTO_KEY_RAW; 944*7c478bd9Sstevel@tonic-gate enckey->ck_data = kmem_zalloc(cdata->keylen, KM_SLEEP); 945*7c478bd9Sstevel@tonic-gate 946*7c478bd9Sstevel@tonic-gate switch (cdata->method) { 947*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_DES_CFB: 948*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_DES_CBC_NULL: 949*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_DES_CBC_MD5: 950*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_DES_CBC_CRC: 951*7c478bd9Sstevel@tonic-gate keybytes = 8; 952*7c478bd9Sstevel@tonic-gate break; 953*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_DES3_CBC_SHA1: 954*7c478bd9Sstevel@tonic-gate keybytes = CRYPT_DES3_KEYBYTES; 955*7c478bd9Sstevel@tonic-gate break; 956*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_ARCFOUR_HMAC_MD5: 957*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_ARCFOUR_HMAC_MD5_EXP: 958*7c478bd9Sstevel@tonic-gate keybytes = CRYPT_ARCFOUR_KEYBYTES; 959*7c478bd9Sstevel@tonic-gate break; 960*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_AES128: 961*7c478bd9Sstevel@tonic-gate keybytes = CRYPT_AES128_KEYBYTES; 962*7c478bd9Sstevel@tonic-gate break; 963*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_AES256: 964*7c478bd9Sstevel@tonic-gate keybytes = CRYPT_AES256_KEYBYTES; 965*7c478bd9Sstevel@tonic-gate break; 966*7c478bd9Sstevel@tonic-gate } 967*7c478bd9Sstevel@tonic-gate 968*7c478bd9Sstevel@tonic-gate /* derive main crypto key */ 969*7c478bd9Sstevel@tonic-gate rv = derive_key(cdata, constdata, sizeof (constdata), 970*7c478bd9Sstevel@tonic-gate enckey->ck_data, keybytes, cdata->blocklen); 971*7c478bd9Sstevel@tonic-gate 972*7c478bd9Sstevel@tonic-gate if (rv == CRYPTO_SUCCESS) { 973*7c478bd9Sstevel@tonic-gate 974*7c478bd9Sstevel@tonic-gate /* Use "0x55" for deriving mac key */ 975*7c478bd9Sstevel@tonic-gate constdata[4] = 0x55; 976*7c478bd9Sstevel@tonic-gate 977*7c478bd9Sstevel@tonic-gate hmackey->ck_length = cdata->keylen * 8; 978*7c478bd9Sstevel@tonic-gate hmackey->ck_format = CRYPTO_KEY_RAW; 979*7c478bd9Sstevel@tonic-gate hmackey->ck_data = kmem_zalloc(cdata->keylen, KM_SLEEP); 980*7c478bd9Sstevel@tonic-gate 981*7c478bd9Sstevel@tonic-gate rv = derive_key(cdata, constdata, sizeof (constdata), 982*7c478bd9Sstevel@tonic-gate hmackey->ck_data, keybytes, 983*7c478bd9Sstevel@tonic-gate cdata->blocklen); 984*7c478bd9Sstevel@tonic-gate } else { 985*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "failed to derive crypto key: %02x", rv); 986*7c478bd9Sstevel@tonic-gate } 987*7c478bd9Sstevel@tonic-gate 988*7c478bd9Sstevel@tonic-gate return (rv); 989*7c478bd9Sstevel@tonic-gate } 990*7c478bd9Sstevel@tonic-gate 991*7c478bd9Sstevel@tonic-gate /* 992*7c478bd9Sstevel@tonic-gate * Compute 3-DES crypto and HMAC. 993*7c478bd9Sstevel@tonic-gate */ 994*7c478bd9Sstevel@tonic-gate static int 995*7c478bd9Sstevel@tonic-gate kef_decr_hmac(struct cipher_data_t *cdata, 996*7c478bd9Sstevel@tonic-gate mblk_t *mp, int length, 997*7c478bd9Sstevel@tonic-gate char *hmac, int hmaclen) 998*7c478bd9Sstevel@tonic-gate { 999*7c478bd9Sstevel@tonic-gate int rv = CRYPTO_FAILED; 1000*7c478bd9Sstevel@tonic-gate 1001*7c478bd9Sstevel@tonic-gate crypto_mechanism_t encr_mech; 1002*7c478bd9Sstevel@tonic-gate crypto_mechanism_t mac_mech; 1003*7c478bd9Sstevel@tonic-gate crypto_data_t dd; 1004*7c478bd9Sstevel@tonic-gate crypto_data_t mac; 1005*7c478bd9Sstevel@tonic-gate iovec_t v1; 1006*7c478bd9Sstevel@tonic-gate 1007*7c478bd9Sstevel@tonic-gate ASSERT(cdata != NULL); 1008*7c478bd9Sstevel@tonic-gate ASSERT(mp != NULL); 1009*7c478bd9Sstevel@tonic-gate ASSERT(hmac != NULL); 1010*7c478bd9Sstevel@tonic-gate 1011*7c478bd9Sstevel@tonic-gate bzero(&dd, sizeof (dd)); 1012*7c478bd9Sstevel@tonic-gate dd.cd_format = CRYPTO_DATA_MBLK; 1013*7c478bd9Sstevel@tonic-gate dd.cd_offset = 0; 1014*7c478bd9Sstevel@tonic-gate dd.cd_length = length; 1015*7c478bd9Sstevel@tonic-gate dd.cd_mp = mp; 1016*7c478bd9Sstevel@tonic-gate 1017*7c478bd9Sstevel@tonic-gate v1.iov_base = hmac; 1018*7c478bd9Sstevel@tonic-gate v1.iov_len = hmaclen; 1019*7c478bd9Sstevel@tonic-gate 1020*7c478bd9Sstevel@tonic-gate mac.cd_format = CRYPTO_DATA_RAW; 1021*7c478bd9Sstevel@tonic-gate mac.cd_offset = 0; 1022*7c478bd9Sstevel@tonic-gate mac.cd_length = hmaclen; 1023*7c478bd9Sstevel@tonic-gate mac.cd_raw = v1; 1024*7c478bd9Sstevel@tonic-gate 1025*7c478bd9Sstevel@tonic-gate /* 1026*7c478bd9Sstevel@tonic-gate * cdata->block holds the IVEC 1027*7c478bd9Sstevel@tonic-gate */ 1028*7c478bd9Sstevel@tonic-gate encr_mech.cm_type = cdata->mech_type; 1029*7c478bd9Sstevel@tonic-gate encr_mech.cm_param = cdata->block; 1030*7c478bd9Sstevel@tonic-gate 1031*7c478bd9Sstevel@tonic-gate if (cdata->block != NULL) 1032*7c478bd9Sstevel@tonic-gate encr_mech.cm_param_len = cdata->blocklen; 1033*7c478bd9Sstevel@tonic-gate else 1034*7c478bd9Sstevel@tonic-gate encr_mech.cm_param_len = 0; 1035*7c478bd9Sstevel@tonic-gate 1036*7c478bd9Sstevel@tonic-gate rv = crypto_decrypt(&encr_mech, &dd, &cdata->d_encr_key, 1037*7c478bd9Sstevel@tonic-gate cdata->enc_tmpl, NULL, NULL); 1038*7c478bd9Sstevel@tonic-gate if (rv != CRYPTO_SUCCESS) { 1039*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "crypto_decrypt failed: %0x", rv); 1040*7c478bd9Sstevel@tonic-gate return (rv); 1041*7c478bd9Sstevel@tonic-gate } 1042*7c478bd9Sstevel@tonic-gate 1043*7c478bd9Sstevel@tonic-gate mac_mech.cm_type = sha1_hmac_mech; 1044*7c478bd9Sstevel@tonic-gate mac_mech.cm_param = NULL; 1045*7c478bd9Sstevel@tonic-gate mac_mech.cm_param_len = 0; 1046*7c478bd9Sstevel@tonic-gate 1047*7c478bd9Sstevel@tonic-gate /* 1048*7c478bd9Sstevel@tonic-gate * Compute MAC of the plaintext decrypted above. 1049*7c478bd9Sstevel@tonic-gate */ 1050*7c478bd9Sstevel@tonic-gate rv = crypto_mac(&mac_mech, &dd, &cdata->d_hmac_key, 1051*7c478bd9Sstevel@tonic-gate cdata->hmac_tmpl, &mac, NULL); 1052*7c478bd9Sstevel@tonic-gate 1053*7c478bd9Sstevel@tonic-gate if (rv != CRYPTO_SUCCESS) { 1054*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "crypto_mac failed: %0x", rv); 1055*7c478bd9Sstevel@tonic-gate } 1056*7c478bd9Sstevel@tonic-gate 1057*7c478bd9Sstevel@tonic-gate return (rv); 1058*7c478bd9Sstevel@tonic-gate } 1059*7c478bd9Sstevel@tonic-gate 1060*7c478bd9Sstevel@tonic-gate /* 1061*7c478bd9Sstevel@tonic-gate * Compute 3-DES crypto and HMAC. 1062*7c478bd9Sstevel@tonic-gate */ 1063*7c478bd9Sstevel@tonic-gate static int 1064*7c478bd9Sstevel@tonic-gate kef_encr_hmac(struct cipher_data_t *cdata, 1065*7c478bd9Sstevel@tonic-gate mblk_t *mp, int length, 1066*7c478bd9Sstevel@tonic-gate char *hmac, int hmaclen) 1067*7c478bd9Sstevel@tonic-gate { 1068*7c478bd9Sstevel@tonic-gate int rv = CRYPTO_FAILED; 1069*7c478bd9Sstevel@tonic-gate 1070*7c478bd9Sstevel@tonic-gate crypto_mechanism_t encr_mech; 1071*7c478bd9Sstevel@tonic-gate crypto_mechanism_t mac_mech; 1072*7c478bd9Sstevel@tonic-gate crypto_data_t dd; 1073*7c478bd9Sstevel@tonic-gate crypto_data_t mac; 1074*7c478bd9Sstevel@tonic-gate iovec_t v1; 1075*7c478bd9Sstevel@tonic-gate 1076*7c478bd9Sstevel@tonic-gate ASSERT(cdata != NULL); 1077*7c478bd9Sstevel@tonic-gate ASSERT(mp != NULL); 1078*7c478bd9Sstevel@tonic-gate ASSERT(hmac != NULL); 1079*7c478bd9Sstevel@tonic-gate 1080*7c478bd9Sstevel@tonic-gate bzero(&dd, sizeof (dd)); 1081*7c478bd9Sstevel@tonic-gate dd.cd_format = CRYPTO_DATA_MBLK; 1082*7c478bd9Sstevel@tonic-gate dd.cd_offset = 0; 1083*7c478bd9Sstevel@tonic-gate dd.cd_length = length; 1084*7c478bd9Sstevel@tonic-gate dd.cd_mp = mp; 1085*7c478bd9Sstevel@tonic-gate 1086*7c478bd9Sstevel@tonic-gate v1.iov_base = hmac; 1087*7c478bd9Sstevel@tonic-gate v1.iov_len = hmaclen; 1088*7c478bd9Sstevel@tonic-gate 1089*7c478bd9Sstevel@tonic-gate mac.cd_format = CRYPTO_DATA_RAW; 1090*7c478bd9Sstevel@tonic-gate mac.cd_offset = 0; 1091*7c478bd9Sstevel@tonic-gate mac.cd_length = hmaclen; 1092*7c478bd9Sstevel@tonic-gate mac.cd_raw = v1; 1093*7c478bd9Sstevel@tonic-gate 1094*7c478bd9Sstevel@tonic-gate /* 1095*7c478bd9Sstevel@tonic-gate * cdata->block holds the IVEC 1096*7c478bd9Sstevel@tonic-gate */ 1097*7c478bd9Sstevel@tonic-gate encr_mech.cm_type = cdata->mech_type; 1098*7c478bd9Sstevel@tonic-gate encr_mech.cm_param = cdata->block; 1099*7c478bd9Sstevel@tonic-gate 1100*7c478bd9Sstevel@tonic-gate if (cdata->block != NULL) 1101*7c478bd9Sstevel@tonic-gate encr_mech.cm_param_len = cdata->blocklen; 1102*7c478bd9Sstevel@tonic-gate else 1103*7c478bd9Sstevel@tonic-gate encr_mech.cm_param_len = 0; 1104*7c478bd9Sstevel@tonic-gate 1105*7c478bd9Sstevel@tonic-gate mac_mech.cm_type = sha1_hmac_mech; 1106*7c478bd9Sstevel@tonic-gate mac_mech.cm_param = NULL; 1107*7c478bd9Sstevel@tonic-gate mac_mech.cm_param_len = 0; 1108*7c478bd9Sstevel@tonic-gate 1109*7c478bd9Sstevel@tonic-gate rv = crypto_mac(&mac_mech, &dd, &cdata->d_hmac_key, 1110*7c478bd9Sstevel@tonic-gate cdata->hmac_tmpl, &mac, NULL); 1111*7c478bd9Sstevel@tonic-gate 1112*7c478bd9Sstevel@tonic-gate if (rv != CRYPTO_SUCCESS) { 1113*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "crypto_mac failed: %0x", rv); 1114*7c478bd9Sstevel@tonic-gate return (rv); 1115*7c478bd9Sstevel@tonic-gate } 1116*7c478bd9Sstevel@tonic-gate 1117*7c478bd9Sstevel@tonic-gate rv = crypto_encrypt(&encr_mech, &dd, &cdata->d_encr_key, 1118*7c478bd9Sstevel@tonic-gate cdata->enc_tmpl, NULL, NULL); 1119*7c478bd9Sstevel@tonic-gate if (rv != CRYPTO_SUCCESS) { 1120*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "crypto_encrypt failed: %0x", rv); 1121*7c478bd9Sstevel@tonic-gate } 1122*7c478bd9Sstevel@tonic-gate 1123*7c478bd9Sstevel@tonic-gate return (rv); 1124*7c478bd9Sstevel@tonic-gate } 1125*7c478bd9Sstevel@tonic-gate 1126*7c478bd9Sstevel@tonic-gate /* 1127*7c478bd9Sstevel@tonic-gate * kef_crypt 1128*7c478bd9Sstevel@tonic-gate * 1129*7c478bd9Sstevel@tonic-gate * Use the Kernel encryption framework to provide the 1130*7c478bd9Sstevel@tonic-gate * crypto operations for the indicated data. 1131*7c478bd9Sstevel@tonic-gate */ 1132*7c478bd9Sstevel@tonic-gate static int 1133*7c478bd9Sstevel@tonic-gate kef_crypt(struct cipher_data_t *cdata, 1134*7c478bd9Sstevel@tonic-gate void *indata, crypto_data_format_t fmt, 1135*7c478bd9Sstevel@tonic-gate size_t length, int mode) 1136*7c478bd9Sstevel@tonic-gate { 1137*7c478bd9Sstevel@tonic-gate int rv = CRYPTO_FAILED; 1138*7c478bd9Sstevel@tonic-gate 1139*7c478bd9Sstevel@tonic-gate crypto_mechanism_t mech; 1140*7c478bd9Sstevel@tonic-gate crypto_key_t crkey; 1141*7c478bd9Sstevel@tonic-gate iovec_t v1; 1142*7c478bd9Sstevel@tonic-gate crypto_data_t d1; 1143*7c478bd9Sstevel@tonic-gate 1144*7c478bd9Sstevel@tonic-gate ASSERT(cdata != NULL); 1145*7c478bd9Sstevel@tonic-gate ASSERT(indata != NULL); 1146*7c478bd9Sstevel@tonic-gate ASSERT(fmt == CRYPTO_DATA_RAW || fmt == CRYPTO_DATA_MBLK); 1147*7c478bd9Sstevel@tonic-gate 1148*7c478bd9Sstevel@tonic-gate bzero(&crkey, sizeof (crkey)); 1149*7c478bd9Sstevel@tonic-gate bzero(&d1, sizeof (d1)); 1150*7c478bd9Sstevel@tonic-gate 1151*7c478bd9Sstevel@tonic-gate crkey.ck_format = CRYPTO_KEY_RAW; 1152*7c478bd9Sstevel@tonic-gate crkey.ck_data = cdata->key; 1153*7c478bd9Sstevel@tonic-gate 1154*7c478bd9Sstevel@tonic-gate /* keys are measured in bits, not bytes, so multiply by 8 */ 1155*7c478bd9Sstevel@tonic-gate crkey.ck_length = cdata->keylen * 8; 1156*7c478bd9Sstevel@tonic-gate 1157*7c478bd9Sstevel@tonic-gate if (fmt == CRYPTO_DATA_RAW) { 1158*7c478bd9Sstevel@tonic-gate v1.iov_base = (char *)indata; 1159*7c478bd9Sstevel@tonic-gate v1.iov_len = length; 1160*7c478bd9Sstevel@tonic-gate } 1161*7c478bd9Sstevel@tonic-gate 1162*7c478bd9Sstevel@tonic-gate d1.cd_format = fmt; 1163*7c478bd9Sstevel@tonic-gate d1.cd_offset = 0; 1164*7c478bd9Sstevel@tonic-gate d1.cd_length = length; 1165*7c478bd9Sstevel@tonic-gate if (fmt == CRYPTO_DATA_RAW) 1166*7c478bd9Sstevel@tonic-gate d1.cd_raw = v1; 1167*7c478bd9Sstevel@tonic-gate else if (fmt == CRYPTO_DATA_MBLK) 1168*7c478bd9Sstevel@tonic-gate d1.cd_mp = (mblk_t *)indata; 1169*7c478bd9Sstevel@tonic-gate 1170*7c478bd9Sstevel@tonic-gate mech.cm_type = cdata->mech_type; 1171*7c478bd9Sstevel@tonic-gate mech.cm_param = cdata->block; 1172*7c478bd9Sstevel@tonic-gate /* 1173*7c478bd9Sstevel@tonic-gate * cdata->block holds the IVEC 1174*7c478bd9Sstevel@tonic-gate */ 1175*7c478bd9Sstevel@tonic-gate if (cdata->block != NULL) 1176*7c478bd9Sstevel@tonic-gate mech.cm_param_len = cdata->blocklen; 1177*7c478bd9Sstevel@tonic-gate else 1178*7c478bd9Sstevel@tonic-gate mech.cm_param_len = 0; 1179*7c478bd9Sstevel@tonic-gate 1180*7c478bd9Sstevel@tonic-gate /* 1181*7c478bd9Sstevel@tonic-gate * encrypt and decrypt in-place 1182*7c478bd9Sstevel@tonic-gate */ 1183*7c478bd9Sstevel@tonic-gate if (mode == CRYPT_ENCRYPT) 1184*7c478bd9Sstevel@tonic-gate rv = crypto_encrypt(&mech, &d1, &crkey, NULL, NULL, NULL); 1185*7c478bd9Sstevel@tonic-gate else 1186*7c478bd9Sstevel@tonic-gate rv = crypto_decrypt(&mech, &d1, &crkey, NULL, NULL, NULL); 1187*7c478bd9Sstevel@tonic-gate 1188*7c478bd9Sstevel@tonic-gate if (rv != CRYPTO_SUCCESS) { 1189*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s returned error %08x", 1190*7c478bd9Sstevel@tonic-gate (mode == CRYPT_ENCRYPT ? "crypto_encrypt" : 1191*7c478bd9Sstevel@tonic-gate "crypto_decrypt"), rv); 1192*7c478bd9Sstevel@tonic-gate return (CRYPTO_FAILED); 1193*7c478bd9Sstevel@tonic-gate } 1194*7c478bd9Sstevel@tonic-gate 1195*7c478bd9Sstevel@tonic-gate return (rv); 1196*7c478bd9Sstevel@tonic-gate } 1197*7c478bd9Sstevel@tonic-gate 1198*7c478bd9Sstevel@tonic-gate static int 1199*7c478bd9Sstevel@tonic-gate do_hmac(crypto_mech_type_t mech, 1200*7c478bd9Sstevel@tonic-gate crypto_key_t *key, 1201*7c478bd9Sstevel@tonic-gate char *data, int datalen, 1202*7c478bd9Sstevel@tonic-gate char *hmac, int hmaclen) 1203*7c478bd9Sstevel@tonic-gate { 1204*7c478bd9Sstevel@tonic-gate int rv = 0; 1205*7c478bd9Sstevel@tonic-gate crypto_mechanism_t mac_mech; 1206*7c478bd9Sstevel@tonic-gate crypto_data_t dd; 1207*7c478bd9Sstevel@tonic-gate crypto_data_t mac; 1208*7c478bd9Sstevel@tonic-gate iovec_t vdata, vmac; 1209*7c478bd9Sstevel@tonic-gate 1210*7c478bd9Sstevel@tonic-gate mac_mech.cm_type = mech; 1211*7c478bd9Sstevel@tonic-gate mac_mech.cm_param = NULL; 1212*7c478bd9Sstevel@tonic-gate mac_mech.cm_param_len = 0; 1213*7c478bd9Sstevel@tonic-gate 1214*7c478bd9Sstevel@tonic-gate vdata.iov_base = data; 1215*7c478bd9Sstevel@tonic-gate vdata.iov_len = datalen; 1216*7c478bd9Sstevel@tonic-gate 1217*7c478bd9Sstevel@tonic-gate bzero(&dd, sizeof (dd)); 1218*7c478bd9Sstevel@tonic-gate dd.cd_format = CRYPTO_DATA_RAW; 1219*7c478bd9Sstevel@tonic-gate dd.cd_offset = 0; 1220*7c478bd9Sstevel@tonic-gate dd.cd_length = datalen; 1221*7c478bd9Sstevel@tonic-gate dd.cd_raw = vdata; 1222*7c478bd9Sstevel@tonic-gate 1223*7c478bd9Sstevel@tonic-gate vmac.iov_base = hmac; 1224*7c478bd9Sstevel@tonic-gate vmac.iov_len = hmaclen; 1225*7c478bd9Sstevel@tonic-gate 1226*7c478bd9Sstevel@tonic-gate mac.cd_format = CRYPTO_DATA_RAW; 1227*7c478bd9Sstevel@tonic-gate mac.cd_offset = 0; 1228*7c478bd9Sstevel@tonic-gate mac.cd_length = hmaclen; 1229*7c478bd9Sstevel@tonic-gate mac.cd_raw = vmac; 1230*7c478bd9Sstevel@tonic-gate 1231*7c478bd9Sstevel@tonic-gate /* 1232*7c478bd9Sstevel@tonic-gate * Compute MAC of the plaintext decrypted above. 1233*7c478bd9Sstevel@tonic-gate */ 1234*7c478bd9Sstevel@tonic-gate rv = crypto_mac(&mac_mech, &dd, key, NULL, &mac, NULL); 1235*7c478bd9Sstevel@tonic-gate 1236*7c478bd9Sstevel@tonic-gate if (rv != CRYPTO_SUCCESS) { 1237*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "crypto_mac failed: %0x", rv); 1238*7c478bd9Sstevel@tonic-gate } 1239*7c478bd9Sstevel@tonic-gate 1240*7c478bd9Sstevel@tonic-gate return (rv); 1241*7c478bd9Sstevel@tonic-gate } 1242*7c478bd9Sstevel@tonic-gate 1243*7c478bd9Sstevel@tonic-gate #define XOR_BLOCK(src, dst) \ 1244*7c478bd9Sstevel@tonic-gate (dst)[0] ^= (src)[0]; \ 1245*7c478bd9Sstevel@tonic-gate (dst)[1] ^= (src)[1]; \ 1246*7c478bd9Sstevel@tonic-gate (dst)[2] ^= (src)[2]; \ 1247*7c478bd9Sstevel@tonic-gate (dst)[3] ^= (src)[3]; \ 1248*7c478bd9Sstevel@tonic-gate (dst)[4] ^= (src)[4]; \ 1249*7c478bd9Sstevel@tonic-gate (dst)[5] ^= (src)[5]; \ 1250*7c478bd9Sstevel@tonic-gate (dst)[6] ^= (src)[6]; \ 1251*7c478bd9Sstevel@tonic-gate (dst)[7] ^= (src)[7]; \ 1252*7c478bd9Sstevel@tonic-gate (dst)[8] ^= (src)[8]; \ 1253*7c478bd9Sstevel@tonic-gate (dst)[9] ^= (src)[9]; \ 1254*7c478bd9Sstevel@tonic-gate (dst)[10] ^= (src)[10]; \ 1255*7c478bd9Sstevel@tonic-gate (dst)[11] ^= (src)[11]; \ 1256*7c478bd9Sstevel@tonic-gate (dst)[12] ^= (src)[12]; \ 1257*7c478bd9Sstevel@tonic-gate (dst)[13] ^= (src)[13]; \ 1258*7c478bd9Sstevel@tonic-gate (dst)[14] ^= (src)[14]; \ 1259*7c478bd9Sstevel@tonic-gate (dst)[15] ^= (src)[15] 1260*7c478bd9Sstevel@tonic-gate 1261*7c478bd9Sstevel@tonic-gate #define xorblock(x, y) XOR_BLOCK(y, x) 1262*7c478bd9Sstevel@tonic-gate 1263*7c478bd9Sstevel@tonic-gate static int 1264*7c478bd9Sstevel@tonic-gate aes_cbc_cts_encrypt(struct tmodinfo *tmi, uchar_t *plain, size_t length) 1265*7c478bd9Sstevel@tonic-gate { 1266*7c478bd9Sstevel@tonic-gate int result = CRYPTO_SUCCESS; 1267*7c478bd9Sstevel@tonic-gate unsigned char tmp[DEFAULT_AES_BLOCKLEN]; 1268*7c478bd9Sstevel@tonic-gate unsigned char tmp2[DEFAULT_AES_BLOCKLEN]; 1269*7c478bd9Sstevel@tonic-gate unsigned char tmp3[DEFAULT_AES_BLOCKLEN]; 1270*7c478bd9Sstevel@tonic-gate int nblocks = 0, blockno; 1271*7c478bd9Sstevel@tonic-gate crypto_data_t ct, pt; 1272*7c478bd9Sstevel@tonic-gate crypto_mechanism_t mech; 1273*7c478bd9Sstevel@tonic-gate 1274*7c478bd9Sstevel@tonic-gate mech.cm_type = tmi->enc_data.mech_type; 1275*7c478bd9Sstevel@tonic-gate if (tmi->enc_data.ivlen > 0 && tmi->enc_data.ivec != NULL) { 1276*7c478bd9Sstevel@tonic-gate bcopy(tmi->enc_data.ivec, tmp, DEFAULT_AES_BLOCKLEN); 1277*7c478bd9Sstevel@tonic-gate mech.cm_param = tmi->enc_data.ivec; 1278*7c478bd9Sstevel@tonic-gate mech.cm_param_len = tmi->enc_data.ivlen; 1279*7c478bd9Sstevel@tonic-gate } else { 1280*7c478bd9Sstevel@tonic-gate bzero(tmp, sizeof (tmp)); 1281*7c478bd9Sstevel@tonic-gate mech.cm_param = NULL; 1282*7c478bd9Sstevel@tonic-gate mech.cm_param_len = 0; 1283*7c478bd9Sstevel@tonic-gate } 1284*7c478bd9Sstevel@tonic-gate 1285*7c478bd9Sstevel@tonic-gate nblocks = (length + DEFAULT_AES_BLOCKLEN - 1) / DEFAULT_AES_BLOCKLEN; 1286*7c478bd9Sstevel@tonic-gate 1287*7c478bd9Sstevel@tonic-gate bzero(&ct, sizeof (crypto_data_t)); 1288*7c478bd9Sstevel@tonic-gate bzero(&pt, sizeof (crypto_data_t)); 1289*7c478bd9Sstevel@tonic-gate 1290*7c478bd9Sstevel@tonic-gate if (nblocks == 1) { 1291*7c478bd9Sstevel@tonic-gate pt.cd_format = CRYPTO_DATA_RAW; 1292*7c478bd9Sstevel@tonic-gate pt.cd_length = length; 1293*7c478bd9Sstevel@tonic-gate pt.cd_raw.iov_base = (char *)plain; 1294*7c478bd9Sstevel@tonic-gate pt.cd_raw.iov_len = length; 1295*7c478bd9Sstevel@tonic-gate 1296*7c478bd9Sstevel@tonic-gate result = crypto_encrypt(&mech, &pt, 1297*7c478bd9Sstevel@tonic-gate &tmi->enc_data.d_encr_key, NULL, NULL, NULL); 1298*7c478bd9Sstevel@tonic-gate 1299*7c478bd9Sstevel@tonic-gate if (result != CRYPTO_SUCCESS) { 1300*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "aes_cbc_cts_encrypt: " 1301*7c478bd9Sstevel@tonic-gate "crypto_encrypt failed: %0x", result); 1302*7c478bd9Sstevel@tonic-gate } 1303*7c478bd9Sstevel@tonic-gate } else { 1304*7c478bd9Sstevel@tonic-gate size_t nleft; 1305*7c478bd9Sstevel@tonic-gate 1306*7c478bd9Sstevel@tonic-gate ct.cd_format = CRYPTO_DATA_RAW; 1307*7c478bd9Sstevel@tonic-gate ct.cd_offset = 0; 1308*7c478bd9Sstevel@tonic-gate ct.cd_length = DEFAULT_AES_BLOCKLEN; 1309*7c478bd9Sstevel@tonic-gate 1310*7c478bd9Sstevel@tonic-gate pt.cd_format = CRYPTO_DATA_RAW; 1311*7c478bd9Sstevel@tonic-gate pt.cd_offset = 0; 1312*7c478bd9Sstevel@tonic-gate pt.cd_length = DEFAULT_AES_BLOCKLEN; 1313*7c478bd9Sstevel@tonic-gate 1314*7c478bd9Sstevel@tonic-gate result = crypto_encrypt_init(&mech, 1315*7c478bd9Sstevel@tonic-gate &tmi->enc_data.d_encr_key, 1316*7c478bd9Sstevel@tonic-gate tmi->enc_data.enc_tmpl, 1317*7c478bd9Sstevel@tonic-gate &tmi->enc_data.ctx, NULL); 1318*7c478bd9Sstevel@tonic-gate 1319*7c478bd9Sstevel@tonic-gate if (result != CRYPTO_SUCCESS) { 1320*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "aes_cbc_cts_encrypt: " 1321*7c478bd9Sstevel@tonic-gate "crypto_encrypt_init failed: %0x", result); 1322*7c478bd9Sstevel@tonic-gate goto cleanup; 1323*7c478bd9Sstevel@tonic-gate } 1324*7c478bd9Sstevel@tonic-gate 1325*7c478bd9Sstevel@tonic-gate for (blockno = 0; blockno < nblocks - 2; blockno++) { 1326*7c478bd9Sstevel@tonic-gate xorblock(tmp, plain + blockno * DEFAULT_AES_BLOCKLEN); 1327*7c478bd9Sstevel@tonic-gate 1328*7c478bd9Sstevel@tonic-gate pt.cd_raw.iov_base = (char *)tmp; 1329*7c478bd9Sstevel@tonic-gate pt.cd_raw.iov_len = DEFAULT_AES_BLOCKLEN; 1330*7c478bd9Sstevel@tonic-gate 1331*7c478bd9Sstevel@tonic-gate ct.cd_raw.iov_base = (char *)plain + 1332*7c478bd9Sstevel@tonic-gate blockno * DEFAULT_AES_BLOCKLEN; 1333*7c478bd9Sstevel@tonic-gate ct.cd_raw.iov_len = DEFAULT_AES_BLOCKLEN; 1334*7c478bd9Sstevel@tonic-gate 1335*7c478bd9Sstevel@tonic-gate result = crypto_encrypt_update(tmi->enc_data.ctx, 1336*7c478bd9Sstevel@tonic-gate &pt, &ct, NULL); 1337*7c478bd9Sstevel@tonic-gate 1338*7c478bd9Sstevel@tonic-gate if (result != CRYPTO_SUCCESS) { 1339*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "aes_cbc_cts_encrypt: " 1340*7c478bd9Sstevel@tonic-gate "crypto_encrypt_update failed: %0x", 1341*7c478bd9Sstevel@tonic-gate result); 1342*7c478bd9Sstevel@tonic-gate goto cleanup; 1343*7c478bd9Sstevel@tonic-gate } 1344*7c478bd9Sstevel@tonic-gate /* copy result over original bytes */ 1345*7c478bd9Sstevel@tonic-gate /* make another copy for the next XOR step */ 1346*7c478bd9Sstevel@tonic-gate bcopy(plain + blockno * DEFAULT_AES_BLOCKLEN, 1347*7c478bd9Sstevel@tonic-gate tmp, DEFAULT_AES_BLOCKLEN); 1348*7c478bd9Sstevel@tonic-gate } 1349*7c478bd9Sstevel@tonic-gate /* XOR cipher text from n-3 with plain text from n-2 */ 1350*7c478bd9Sstevel@tonic-gate xorblock(tmp, plain + (nblocks - 2) * DEFAULT_AES_BLOCKLEN); 1351*7c478bd9Sstevel@tonic-gate 1352*7c478bd9Sstevel@tonic-gate pt.cd_raw.iov_base = (char *)tmp; 1353*7c478bd9Sstevel@tonic-gate pt.cd_raw.iov_len = DEFAULT_AES_BLOCKLEN; 1354*7c478bd9Sstevel@tonic-gate 1355*7c478bd9Sstevel@tonic-gate ct.cd_raw.iov_base = (char *)tmp2; 1356*7c478bd9Sstevel@tonic-gate ct.cd_raw.iov_len = DEFAULT_AES_BLOCKLEN; 1357*7c478bd9Sstevel@tonic-gate 1358*7c478bd9Sstevel@tonic-gate /* encrypt XOR-ed block N-2 */ 1359*7c478bd9Sstevel@tonic-gate result = crypto_encrypt_update(tmi->enc_data.ctx, 1360*7c478bd9Sstevel@tonic-gate &pt, &ct, NULL); 1361*7c478bd9Sstevel@tonic-gate if (result != CRYPTO_SUCCESS) { 1362*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "aes_cbc_cts_encrypt: " 1363*7c478bd9Sstevel@tonic-gate "crypto_encrypt_update(2) failed: %0x", 1364*7c478bd9Sstevel@tonic-gate result); 1365*7c478bd9Sstevel@tonic-gate goto cleanup; 1366*7c478bd9Sstevel@tonic-gate } 1367*7c478bd9Sstevel@tonic-gate nleft = length - (nblocks - 1) * DEFAULT_AES_BLOCKLEN; 1368*7c478bd9Sstevel@tonic-gate 1369*7c478bd9Sstevel@tonic-gate bzero(tmp3, sizeof (tmp3)); 1370*7c478bd9Sstevel@tonic-gate /* Save final plaintext bytes from n-1 */ 1371*7c478bd9Sstevel@tonic-gate bcopy(plain + (nblocks - 1) * DEFAULT_AES_BLOCKLEN, tmp3, 1372*7c478bd9Sstevel@tonic-gate nleft); 1373*7c478bd9Sstevel@tonic-gate 1374*7c478bd9Sstevel@tonic-gate /* Overwrite n-1 with cipher text from n-2 */ 1375*7c478bd9Sstevel@tonic-gate bcopy(tmp2, plain + (nblocks - 1) * DEFAULT_AES_BLOCKLEN, 1376*7c478bd9Sstevel@tonic-gate nleft); 1377*7c478bd9Sstevel@tonic-gate 1378*7c478bd9Sstevel@tonic-gate bcopy(tmp2, tmp, DEFAULT_AES_BLOCKLEN); 1379*7c478bd9Sstevel@tonic-gate /* XOR cipher text from n-1 with plain text from n-1 */ 1380*7c478bd9Sstevel@tonic-gate xorblock(tmp, tmp3); 1381*7c478bd9Sstevel@tonic-gate 1382*7c478bd9Sstevel@tonic-gate pt.cd_raw.iov_base = (char *)tmp; 1383*7c478bd9Sstevel@tonic-gate pt.cd_raw.iov_len = DEFAULT_AES_BLOCKLEN; 1384*7c478bd9Sstevel@tonic-gate 1385*7c478bd9Sstevel@tonic-gate ct.cd_raw.iov_base = (char *)tmp2; 1386*7c478bd9Sstevel@tonic-gate ct.cd_raw.iov_len = DEFAULT_AES_BLOCKLEN; 1387*7c478bd9Sstevel@tonic-gate 1388*7c478bd9Sstevel@tonic-gate /* encrypt block N-2 */ 1389*7c478bd9Sstevel@tonic-gate result = crypto_encrypt_update(tmi->enc_data.ctx, 1390*7c478bd9Sstevel@tonic-gate &pt, &ct, NULL); 1391*7c478bd9Sstevel@tonic-gate 1392*7c478bd9Sstevel@tonic-gate if (result != CRYPTO_SUCCESS) { 1393*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "aes_cbc_cts_encrypt: " 1394*7c478bd9Sstevel@tonic-gate "crypto_encrypt_update(3) failed: %0x", 1395*7c478bd9Sstevel@tonic-gate result); 1396*7c478bd9Sstevel@tonic-gate goto cleanup; 1397*7c478bd9Sstevel@tonic-gate } 1398*7c478bd9Sstevel@tonic-gate 1399*7c478bd9Sstevel@tonic-gate bcopy(tmp2, plain + (nblocks - 2) * DEFAULT_AES_BLOCKLEN, 1400*7c478bd9Sstevel@tonic-gate DEFAULT_AES_BLOCKLEN); 1401*7c478bd9Sstevel@tonic-gate 1402*7c478bd9Sstevel@tonic-gate 1403*7c478bd9Sstevel@tonic-gate ct.cd_raw.iov_base = (char *)tmp2; 1404*7c478bd9Sstevel@tonic-gate ct.cd_raw.iov_len = DEFAULT_AES_BLOCKLEN; 1405*7c478bd9Sstevel@tonic-gate 1406*7c478bd9Sstevel@tonic-gate /* 1407*7c478bd9Sstevel@tonic-gate * Ignore the output on the final step. 1408*7c478bd9Sstevel@tonic-gate */ 1409*7c478bd9Sstevel@tonic-gate result = crypto_encrypt_final(tmi->enc_data.ctx, &ct, NULL); 1410*7c478bd9Sstevel@tonic-gate if (result != CRYPTO_SUCCESS) { 1411*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "aes_cbc_cts_encrypt: " 1412*7c478bd9Sstevel@tonic-gate "crypto_encrypt_final(3) failed: %0x", 1413*7c478bd9Sstevel@tonic-gate result); 1414*7c478bd9Sstevel@tonic-gate } 1415*7c478bd9Sstevel@tonic-gate tmi->enc_data.ctx = NULL; 1416*7c478bd9Sstevel@tonic-gate } 1417*7c478bd9Sstevel@tonic-gate cleanup: 1418*7c478bd9Sstevel@tonic-gate bzero(tmp, sizeof (tmp)); 1419*7c478bd9Sstevel@tonic-gate bzero(tmp2, sizeof (tmp)); 1420*7c478bd9Sstevel@tonic-gate bzero(tmp3, sizeof (tmp)); 1421*7c478bd9Sstevel@tonic-gate bzero(tmi->enc_data.block, tmi->enc_data.blocklen); 1422*7c478bd9Sstevel@tonic-gate return (result); 1423*7c478bd9Sstevel@tonic-gate } 1424*7c478bd9Sstevel@tonic-gate 1425*7c478bd9Sstevel@tonic-gate static int 1426*7c478bd9Sstevel@tonic-gate aes_cbc_cts_decrypt(struct tmodinfo *tmi, uchar_t *buff, size_t length) 1427*7c478bd9Sstevel@tonic-gate { 1428*7c478bd9Sstevel@tonic-gate int result = CRYPTO_SUCCESS; 1429*7c478bd9Sstevel@tonic-gate unsigned char tmp[DEFAULT_AES_BLOCKLEN]; 1430*7c478bd9Sstevel@tonic-gate unsigned char tmp2[DEFAULT_AES_BLOCKLEN]; 1431*7c478bd9Sstevel@tonic-gate unsigned char tmp3[DEFAULT_AES_BLOCKLEN]; 1432*7c478bd9Sstevel@tonic-gate int nblocks = 0, blockno; 1433*7c478bd9Sstevel@tonic-gate crypto_data_t ct, pt; 1434*7c478bd9Sstevel@tonic-gate crypto_mechanism_t mech; 1435*7c478bd9Sstevel@tonic-gate 1436*7c478bd9Sstevel@tonic-gate mech.cm_type = tmi->enc_data.mech_type; 1437*7c478bd9Sstevel@tonic-gate 1438*7c478bd9Sstevel@tonic-gate if (tmi->dec_data.ivec_usage != IVEC_NEVER && 1439*7c478bd9Sstevel@tonic-gate tmi->dec_data.ivlen > 0 && tmi->dec_data.ivec != NULL) { 1440*7c478bd9Sstevel@tonic-gate bcopy(tmi->dec_data.ivec, tmp, DEFAULT_AES_BLOCKLEN); 1441*7c478bd9Sstevel@tonic-gate mech.cm_param = tmi->dec_data.ivec; 1442*7c478bd9Sstevel@tonic-gate mech.cm_param_len = tmi->dec_data.ivlen; 1443*7c478bd9Sstevel@tonic-gate } else { 1444*7c478bd9Sstevel@tonic-gate bzero(tmp, sizeof (tmp)); 1445*7c478bd9Sstevel@tonic-gate mech.cm_param_len = 0; 1446*7c478bd9Sstevel@tonic-gate mech.cm_param = NULL; 1447*7c478bd9Sstevel@tonic-gate } 1448*7c478bd9Sstevel@tonic-gate nblocks = (length + DEFAULT_AES_BLOCKLEN - 1) / DEFAULT_AES_BLOCKLEN; 1449*7c478bd9Sstevel@tonic-gate 1450*7c478bd9Sstevel@tonic-gate bzero(&pt, sizeof (pt)); 1451*7c478bd9Sstevel@tonic-gate bzero(&ct, sizeof (ct)); 1452*7c478bd9Sstevel@tonic-gate 1453*7c478bd9Sstevel@tonic-gate if (nblocks == 1) { 1454*7c478bd9Sstevel@tonic-gate ct.cd_format = CRYPTO_DATA_RAW; 1455*7c478bd9Sstevel@tonic-gate ct.cd_length = length; 1456*7c478bd9Sstevel@tonic-gate ct.cd_raw.iov_base = (char *)buff; 1457*7c478bd9Sstevel@tonic-gate ct.cd_raw.iov_len = length; 1458*7c478bd9Sstevel@tonic-gate 1459*7c478bd9Sstevel@tonic-gate result = crypto_decrypt(&mech, &ct, 1460*7c478bd9Sstevel@tonic-gate &tmi->dec_data.d_encr_key, NULL, NULL, NULL); 1461*7c478bd9Sstevel@tonic-gate 1462*7c478bd9Sstevel@tonic-gate if (result != CRYPTO_SUCCESS) { 1463*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "aes_cbc_cts_decrypt: " 1464*7c478bd9Sstevel@tonic-gate "crypto_decrypt failed: %0x", result); 1465*7c478bd9Sstevel@tonic-gate goto cleanup; 1466*7c478bd9Sstevel@tonic-gate } 1467*7c478bd9Sstevel@tonic-gate } else { 1468*7c478bd9Sstevel@tonic-gate ct.cd_format = CRYPTO_DATA_RAW; 1469*7c478bd9Sstevel@tonic-gate ct.cd_offset = 0; 1470*7c478bd9Sstevel@tonic-gate ct.cd_length = DEFAULT_AES_BLOCKLEN; 1471*7c478bd9Sstevel@tonic-gate 1472*7c478bd9Sstevel@tonic-gate pt.cd_format = CRYPTO_DATA_RAW; 1473*7c478bd9Sstevel@tonic-gate pt.cd_offset = 0; 1474*7c478bd9Sstevel@tonic-gate pt.cd_length = DEFAULT_AES_BLOCKLEN; 1475*7c478bd9Sstevel@tonic-gate 1476*7c478bd9Sstevel@tonic-gate result = crypto_encrypt_init(&mech, 1477*7c478bd9Sstevel@tonic-gate &tmi->dec_data.d_encr_key, 1478*7c478bd9Sstevel@tonic-gate tmi->dec_data.enc_tmpl, 1479*7c478bd9Sstevel@tonic-gate &tmi->dec_data.ctx, NULL); 1480*7c478bd9Sstevel@tonic-gate 1481*7c478bd9Sstevel@tonic-gate if (result != CRYPTO_SUCCESS) { 1482*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "aes_cbc_cts_decrypt: " 1483*7c478bd9Sstevel@tonic-gate "crypto_decrypt_init failed: %0x", result); 1484*7c478bd9Sstevel@tonic-gate goto cleanup; 1485*7c478bd9Sstevel@tonic-gate } 1486*7c478bd9Sstevel@tonic-gate for (blockno = 0; blockno < nblocks - 2; blockno++) { 1487*7c478bd9Sstevel@tonic-gate ct.cd_raw.iov_base = (char *)buff + 1488*7c478bd9Sstevel@tonic-gate (blockno * DEFAULT_AES_BLOCKLEN); 1489*7c478bd9Sstevel@tonic-gate ct.cd_raw.iov_len = DEFAULT_AES_BLOCKLEN; 1490*7c478bd9Sstevel@tonic-gate 1491*7c478bd9Sstevel@tonic-gate pt.cd_raw.iov_base = (char *)tmp2; 1492*7c478bd9Sstevel@tonic-gate pt.cd_raw.iov_len = DEFAULT_AES_BLOCKLEN; 1493*7c478bd9Sstevel@tonic-gate 1494*7c478bd9Sstevel@tonic-gate /* 1495*7c478bd9Sstevel@tonic-gate * Save the input to the decrypt so it can 1496*7c478bd9Sstevel@tonic-gate * be used later for an XOR operation 1497*7c478bd9Sstevel@tonic-gate */ 1498*7c478bd9Sstevel@tonic-gate bcopy(buff + (blockno * DEFAULT_AES_BLOCKLEN), 1499*7c478bd9Sstevel@tonic-gate tmi->dec_data.block, DEFAULT_AES_BLOCKLEN); 1500*7c478bd9Sstevel@tonic-gate 1501*7c478bd9Sstevel@tonic-gate result = crypto_decrypt_update(&tmi->dec_data.ctx, 1502*7c478bd9Sstevel@tonic-gate &ct, &pt, NULL); 1503*7c478bd9Sstevel@tonic-gate if (result != CRYPTO_SUCCESS) { 1504*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "aes_cbc_cts_decrypt: " 1505*7c478bd9Sstevel@tonic-gate "crypto_decrypt_update(1) error - " 1506*7c478bd9Sstevel@tonic-gate "result = 0x%08x", result); 1507*7c478bd9Sstevel@tonic-gate goto cleanup; 1508*7c478bd9Sstevel@tonic-gate } 1509*7c478bd9Sstevel@tonic-gate xorblock(tmp2, tmp); 1510*7c478bd9Sstevel@tonic-gate bcopy(tmp2, buff + blockno * DEFAULT_AES_BLOCKLEN, 1511*7c478bd9Sstevel@tonic-gate DEFAULT_AES_BLOCKLEN); 1512*7c478bd9Sstevel@tonic-gate /* 1513*7c478bd9Sstevel@tonic-gate * The original cipher text is used as the xor 1514*7c478bd9Sstevel@tonic-gate * for the next block, save it here. 1515*7c478bd9Sstevel@tonic-gate */ 1516*7c478bd9Sstevel@tonic-gate bcopy(tmi->dec_data.block, tmp, DEFAULT_AES_BLOCKLEN); 1517*7c478bd9Sstevel@tonic-gate } 1518*7c478bd9Sstevel@tonic-gate ct.cd_raw.iov_base = (char *)buff + 1519*7c478bd9Sstevel@tonic-gate ((nblocks - 2) * DEFAULT_AES_BLOCKLEN); 1520*7c478bd9Sstevel@tonic-gate ct.cd_raw.iov_len = DEFAULT_AES_BLOCKLEN; 1521*7c478bd9Sstevel@tonic-gate pt.cd_raw.iov_base = (char *)tmp2; 1522*7c478bd9Sstevel@tonic-gate pt.cd_raw.iov_len = DEFAULT_AES_BLOCKLEN; 1523*7c478bd9Sstevel@tonic-gate 1524*7c478bd9Sstevel@tonic-gate result = crypto_decrypt_update(tmi->dec_data.ctx, 1525*7c478bd9Sstevel@tonic-gate &ct, &pt, NULL); 1526*7c478bd9Sstevel@tonic-gate if (result != CRYPTO_SUCCESS) { 1527*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 1528*7c478bd9Sstevel@tonic-gate "aes_cbc_cts_decrypt: " 1529*7c478bd9Sstevel@tonic-gate "crypto_decrypt_update(2) error -" 1530*7c478bd9Sstevel@tonic-gate " result = 0x%08x", result); 1531*7c478bd9Sstevel@tonic-gate goto cleanup; 1532*7c478bd9Sstevel@tonic-gate } 1533*7c478bd9Sstevel@tonic-gate bzero(tmp3, sizeof (tmp3)); 1534*7c478bd9Sstevel@tonic-gate bcopy(buff + (nblocks - 1) * DEFAULT_AES_BLOCKLEN, tmp3, 1535*7c478bd9Sstevel@tonic-gate length - ((nblocks - 1) * DEFAULT_AES_BLOCKLEN)); 1536*7c478bd9Sstevel@tonic-gate 1537*7c478bd9Sstevel@tonic-gate xorblock(tmp2, tmp3); 1538*7c478bd9Sstevel@tonic-gate bcopy(tmp2, buff + (nblocks - 1) * DEFAULT_AES_BLOCKLEN, 1539*7c478bd9Sstevel@tonic-gate length - ((nblocks - 1) * DEFAULT_AES_BLOCKLEN)); 1540*7c478bd9Sstevel@tonic-gate 1541*7c478bd9Sstevel@tonic-gate /* 2nd to last block ... */ 1542*7c478bd9Sstevel@tonic-gate bcopy(tmp3, tmp2, 1543*7c478bd9Sstevel@tonic-gate length - ((nblocks - 1) * DEFAULT_AES_BLOCKLEN)); 1544*7c478bd9Sstevel@tonic-gate 1545*7c478bd9Sstevel@tonic-gate ct.cd_raw.iov_base = (char *)tmp2; 1546*7c478bd9Sstevel@tonic-gate ct.cd_raw.iov_len = DEFAULT_AES_BLOCKLEN; 1547*7c478bd9Sstevel@tonic-gate pt.cd_raw.iov_base = (char *)tmp3; 1548*7c478bd9Sstevel@tonic-gate pt.cd_raw.iov_len = DEFAULT_AES_BLOCKLEN; 1549*7c478bd9Sstevel@tonic-gate 1550*7c478bd9Sstevel@tonic-gate result = crypto_decrypt_update(tmi->dec_data.ctx, 1551*7c478bd9Sstevel@tonic-gate &ct, &pt, NULL); 1552*7c478bd9Sstevel@tonic-gate if (result != CRYPTO_SUCCESS) { 1553*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 1554*7c478bd9Sstevel@tonic-gate "aes_cbc_cts_decrypt: " 1555*7c478bd9Sstevel@tonic-gate "crypto_decrypt_update(3) error - " 1556*7c478bd9Sstevel@tonic-gate "result = 0x%08x", result); 1557*7c478bd9Sstevel@tonic-gate goto cleanup; 1558*7c478bd9Sstevel@tonic-gate } 1559*7c478bd9Sstevel@tonic-gate xorblock(tmp3, tmp); 1560*7c478bd9Sstevel@tonic-gate 1561*7c478bd9Sstevel@tonic-gate 1562*7c478bd9Sstevel@tonic-gate /* Finally, update the 2nd to last block and we are done. */ 1563*7c478bd9Sstevel@tonic-gate bcopy(tmp3, buff + (nblocks - 2) * DEFAULT_AES_BLOCKLEN, 1564*7c478bd9Sstevel@tonic-gate DEFAULT_AES_BLOCKLEN); 1565*7c478bd9Sstevel@tonic-gate 1566*7c478bd9Sstevel@tonic-gate /* Do Final step, but ignore output */ 1567*7c478bd9Sstevel@tonic-gate pt.cd_raw.iov_base = (char *)tmp2; 1568*7c478bd9Sstevel@tonic-gate pt.cd_raw.iov_len = DEFAULT_AES_BLOCKLEN; 1569*7c478bd9Sstevel@tonic-gate result = crypto_decrypt_final(tmi->dec_data.ctx, &pt, NULL); 1570*7c478bd9Sstevel@tonic-gate if (result != CRYPTO_SUCCESS) { 1571*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "aes_cbc_cts_decrypt: " 1572*7c478bd9Sstevel@tonic-gate "crypto_decrypt_final error - " 1573*7c478bd9Sstevel@tonic-gate "result = 0x%0x", result); 1574*7c478bd9Sstevel@tonic-gate } 1575*7c478bd9Sstevel@tonic-gate tmi->dec_data.ctx = NULL; 1576*7c478bd9Sstevel@tonic-gate } 1577*7c478bd9Sstevel@tonic-gate 1578*7c478bd9Sstevel@tonic-gate cleanup: 1579*7c478bd9Sstevel@tonic-gate bzero(tmp, sizeof (tmp)); 1580*7c478bd9Sstevel@tonic-gate bzero(tmp2, sizeof (tmp)); 1581*7c478bd9Sstevel@tonic-gate bzero(tmp3, sizeof (tmp)); 1582*7c478bd9Sstevel@tonic-gate bzero(tmi->dec_data.block, tmi->dec_data.blocklen); 1583*7c478bd9Sstevel@tonic-gate return (result); 1584*7c478bd9Sstevel@tonic-gate } 1585*7c478bd9Sstevel@tonic-gate 1586*7c478bd9Sstevel@tonic-gate /* 1587*7c478bd9Sstevel@tonic-gate * AES decrypt 1588*7c478bd9Sstevel@tonic-gate * 1589*7c478bd9Sstevel@tonic-gate * format of ciphertext when using AES 1590*7c478bd9Sstevel@tonic-gate * +-------------+------------+------------+ 1591*7c478bd9Sstevel@tonic-gate * | confounder | msg-data | hmac | 1592*7c478bd9Sstevel@tonic-gate * +-------------+------------+------------+ 1593*7c478bd9Sstevel@tonic-gate */ 1594*7c478bd9Sstevel@tonic-gate static mblk_t * 1595*7c478bd9Sstevel@tonic-gate aes_decrypt(queue_t *q, struct tmodinfo *tmi, mblk_t *mp, 1596*7c478bd9Sstevel@tonic-gate hash_info_t *hash) 1597*7c478bd9Sstevel@tonic-gate { 1598*7c478bd9Sstevel@tonic-gate int result; 1599*7c478bd9Sstevel@tonic-gate size_t enclen; 1600*7c478bd9Sstevel@tonic-gate size_t inlen; 1601*7c478bd9Sstevel@tonic-gate uchar_t hmacbuff[64]; 1602*7c478bd9Sstevel@tonic-gate uchar_t tmpiv[DEFAULT_AES_BLOCKLEN]; 1603*7c478bd9Sstevel@tonic-gate 1604*7c478bd9Sstevel@tonic-gate inlen = (size_t)MBLKL(mp); 1605*7c478bd9Sstevel@tonic-gate 1606*7c478bd9Sstevel@tonic-gate enclen = inlen - AES_TRUNCATED_HMAC_LEN; 1607*7c478bd9Sstevel@tonic-gate if (tmi->dec_data.ivec_usage != IVEC_NEVER && 1608*7c478bd9Sstevel@tonic-gate tmi->dec_data.ivec != NULL && tmi->dec_data.ivlen > 0) { 1609*7c478bd9Sstevel@tonic-gate int nblocks = (enclen + DEFAULT_AES_BLOCKLEN - 1) / 1610*7c478bd9Sstevel@tonic-gate DEFAULT_AES_BLOCKLEN; 1611*7c478bd9Sstevel@tonic-gate bcopy(mp->b_rptr + DEFAULT_AES_BLOCKLEN * (nblocks - 2), 1612*7c478bd9Sstevel@tonic-gate tmpiv, DEFAULT_AES_BLOCKLEN); 1613*7c478bd9Sstevel@tonic-gate } 1614*7c478bd9Sstevel@tonic-gate 1615*7c478bd9Sstevel@tonic-gate /* AES Decrypt */ 1616*7c478bd9Sstevel@tonic-gate result = aes_cbc_cts_decrypt(tmi, mp->b_rptr, enclen); 1617*7c478bd9Sstevel@tonic-gate 1618*7c478bd9Sstevel@tonic-gate if (result != CRYPTO_SUCCESS) { 1619*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 1620*7c478bd9Sstevel@tonic-gate "aes_decrypt: aes_cbc_cts_decrypt " 1621*7c478bd9Sstevel@tonic-gate "failed - error %0x", result); 1622*7c478bd9Sstevel@tonic-gate goto cleanup; 1623*7c478bd9Sstevel@tonic-gate } 1624*7c478bd9Sstevel@tonic-gate 1625*7c478bd9Sstevel@tonic-gate /* Verify the HMAC */ 1626*7c478bd9Sstevel@tonic-gate result = do_hmac(sha1_hmac_mech, 1627*7c478bd9Sstevel@tonic-gate &tmi->dec_data.d_hmac_key, 1628*7c478bd9Sstevel@tonic-gate (char *)mp->b_rptr, enclen, 1629*7c478bd9Sstevel@tonic-gate (char *)hmacbuff, hash->hash_len); 1630*7c478bd9Sstevel@tonic-gate 1631*7c478bd9Sstevel@tonic-gate if (result != CRYPTO_SUCCESS) { 1632*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 1633*7c478bd9Sstevel@tonic-gate "aes_decrypt: do_hmac failed - error %0x", result); 1634*7c478bd9Sstevel@tonic-gate goto cleanup; 1635*7c478bd9Sstevel@tonic-gate } 1636*7c478bd9Sstevel@tonic-gate 1637*7c478bd9Sstevel@tonic-gate if (bcmp(hmacbuff, mp->b_rptr + enclen, 1638*7c478bd9Sstevel@tonic-gate AES_TRUNCATED_HMAC_LEN) != 0) { 1639*7c478bd9Sstevel@tonic-gate result = -1; 1640*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "aes_decrypt: checksum verification failed"); 1641*7c478bd9Sstevel@tonic-gate goto cleanup; 1642*7c478bd9Sstevel@tonic-gate } 1643*7c478bd9Sstevel@tonic-gate 1644*7c478bd9Sstevel@tonic-gate /* truncate the mblk at the end of the decrypted text */ 1645*7c478bd9Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + enclen; 1646*7c478bd9Sstevel@tonic-gate 1647*7c478bd9Sstevel@tonic-gate /* Adjust the beginning of the buffer to skip the confounder */ 1648*7c478bd9Sstevel@tonic-gate mp->b_rptr += DEFAULT_AES_BLOCKLEN; 1649*7c478bd9Sstevel@tonic-gate 1650*7c478bd9Sstevel@tonic-gate if (tmi->dec_data.ivec_usage != IVEC_NEVER && 1651*7c478bd9Sstevel@tonic-gate tmi->dec_data.ivec != NULL && tmi->dec_data.ivlen > 0) 1652*7c478bd9Sstevel@tonic-gate bcopy(tmpiv, tmi->dec_data.ivec, DEFAULT_AES_BLOCKLEN); 1653*7c478bd9Sstevel@tonic-gate 1654*7c478bd9Sstevel@tonic-gate cleanup: 1655*7c478bd9Sstevel@tonic-gate if (result != CRYPTO_SUCCESS) { 1656*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_ERROR; 1657*7c478bd9Sstevel@tonic-gate mp->b_rptr = mp->b_datap->db_base; 1658*7c478bd9Sstevel@tonic-gate *mp->b_rptr = EIO; 1659*7c478bd9Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + sizeof (char); 1660*7c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 1661*7c478bd9Sstevel@tonic-gate mp->b_cont = NULL; 1662*7c478bd9Sstevel@tonic-gate qreply(WR(q), mp); 1663*7c478bd9Sstevel@tonic-gate return (NULL); 1664*7c478bd9Sstevel@tonic-gate } 1665*7c478bd9Sstevel@tonic-gate return (mp); 1666*7c478bd9Sstevel@tonic-gate } 1667*7c478bd9Sstevel@tonic-gate 1668*7c478bd9Sstevel@tonic-gate /* 1669*7c478bd9Sstevel@tonic-gate * AES encrypt 1670*7c478bd9Sstevel@tonic-gate * 1671*7c478bd9Sstevel@tonic-gate * format of ciphertext when using AES 1672*7c478bd9Sstevel@tonic-gate * +-------------+------------+------------+ 1673*7c478bd9Sstevel@tonic-gate * | confounder | msg-data | hmac | 1674*7c478bd9Sstevel@tonic-gate * +-------------+------------+------------+ 1675*7c478bd9Sstevel@tonic-gate */ 1676*7c478bd9Sstevel@tonic-gate static mblk_t * 1677*7c478bd9Sstevel@tonic-gate aes_encrypt(queue_t *q, struct tmodinfo *tmi, mblk_t *mp, 1678*7c478bd9Sstevel@tonic-gate hash_info_t *hash) 1679*7c478bd9Sstevel@tonic-gate { 1680*7c478bd9Sstevel@tonic-gate int result; 1681*7c478bd9Sstevel@tonic-gate size_t cipherlen; 1682*7c478bd9Sstevel@tonic-gate size_t inlen; 1683*7c478bd9Sstevel@tonic-gate uchar_t hmacbuff[64]; 1684*7c478bd9Sstevel@tonic-gate 1685*7c478bd9Sstevel@tonic-gate inlen = (size_t)MBLKL(mp); 1686*7c478bd9Sstevel@tonic-gate 1687*7c478bd9Sstevel@tonic-gate cipherlen = encrypt_size(&tmi->enc_data, inlen); 1688*7c478bd9Sstevel@tonic-gate 1689*7c478bd9Sstevel@tonic-gate ASSERT(MBLKSIZE(mp) >= cipherlen); 1690*7c478bd9Sstevel@tonic-gate 1691*7c478bd9Sstevel@tonic-gate /* 1692*7c478bd9Sstevel@tonic-gate * Shift the rptr back enough to insert the confounder. 1693*7c478bd9Sstevel@tonic-gate */ 1694*7c478bd9Sstevel@tonic-gate mp->b_rptr -= DEFAULT_AES_BLOCKLEN; 1695*7c478bd9Sstevel@tonic-gate 1696*7c478bd9Sstevel@tonic-gate /* Get random data for confounder */ 1697*7c478bd9Sstevel@tonic-gate (void) random_get_pseudo_bytes((uint8_t *)mp->b_rptr, 1698*7c478bd9Sstevel@tonic-gate DEFAULT_AES_BLOCKLEN); 1699*7c478bd9Sstevel@tonic-gate 1700*7c478bd9Sstevel@tonic-gate /* 1701*7c478bd9Sstevel@tonic-gate * Because we encrypt in-place, we need to calculate 1702*7c478bd9Sstevel@tonic-gate * the HMAC of the plaintext now, then stick it on 1703*7c478bd9Sstevel@tonic-gate * the end of the ciphertext down below. 1704*7c478bd9Sstevel@tonic-gate */ 1705*7c478bd9Sstevel@tonic-gate result = do_hmac(sha1_hmac_mech, 1706*7c478bd9Sstevel@tonic-gate &tmi->enc_data.d_hmac_key, 1707*7c478bd9Sstevel@tonic-gate (char *)mp->b_rptr, DEFAULT_AES_BLOCKLEN + inlen, 1708*7c478bd9Sstevel@tonic-gate (char *)hmacbuff, hash->hash_len); 1709*7c478bd9Sstevel@tonic-gate 1710*7c478bd9Sstevel@tonic-gate if (result != CRYPTO_SUCCESS) { 1711*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "aes_encrypt: do_hmac failed - error %0x", 1712*7c478bd9Sstevel@tonic-gate result); 1713*7c478bd9Sstevel@tonic-gate goto cleanup; 1714*7c478bd9Sstevel@tonic-gate } 1715*7c478bd9Sstevel@tonic-gate /* Encrypt using AES-CBC-CTS */ 1716*7c478bd9Sstevel@tonic-gate result = aes_cbc_cts_encrypt(tmi, mp->b_rptr, 1717*7c478bd9Sstevel@tonic-gate inlen + DEFAULT_AES_BLOCKLEN); 1718*7c478bd9Sstevel@tonic-gate 1719*7c478bd9Sstevel@tonic-gate if (result != CRYPTO_SUCCESS) { 1720*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "aes_encrypt: aes_cbc_cts_encrypt " 1721*7c478bd9Sstevel@tonic-gate "failed - error %0x", result); 1722*7c478bd9Sstevel@tonic-gate goto cleanup; 1723*7c478bd9Sstevel@tonic-gate } 1724*7c478bd9Sstevel@tonic-gate 1725*7c478bd9Sstevel@tonic-gate /* copy the truncated HMAC to the end of the mblk */ 1726*7c478bd9Sstevel@tonic-gate bcopy(hmacbuff, mp->b_rptr + DEFAULT_AES_BLOCKLEN + inlen, 1727*7c478bd9Sstevel@tonic-gate AES_TRUNCATED_HMAC_LEN); 1728*7c478bd9Sstevel@tonic-gate 1729*7c478bd9Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + cipherlen; 1730*7c478bd9Sstevel@tonic-gate 1731*7c478bd9Sstevel@tonic-gate /* 1732*7c478bd9Sstevel@tonic-gate * The final block of cipher text (not the HMAC) is used 1733*7c478bd9Sstevel@tonic-gate * as the next IV. 1734*7c478bd9Sstevel@tonic-gate */ 1735*7c478bd9Sstevel@tonic-gate if (tmi->enc_data.ivec_usage != IVEC_NEVER && 1736*7c478bd9Sstevel@tonic-gate tmi->enc_data.ivec != NULL) { 1737*7c478bd9Sstevel@tonic-gate int nblocks = (inlen + 2 * DEFAULT_AES_BLOCKLEN - 1) / 1738*7c478bd9Sstevel@tonic-gate DEFAULT_AES_BLOCKLEN; 1739*7c478bd9Sstevel@tonic-gate 1740*7c478bd9Sstevel@tonic-gate bcopy(mp->b_rptr + (nblocks - 2) * DEFAULT_AES_BLOCKLEN, 1741*7c478bd9Sstevel@tonic-gate tmi->enc_data.ivec, DEFAULT_AES_BLOCKLEN); 1742*7c478bd9Sstevel@tonic-gate } 1743*7c478bd9Sstevel@tonic-gate 1744*7c478bd9Sstevel@tonic-gate cleanup: 1745*7c478bd9Sstevel@tonic-gate if (result != CRYPTO_SUCCESS) { 1746*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_ERROR; 1747*7c478bd9Sstevel@tonic-gate mp->b_rptr = mp->b_datap->db_base; 1748*7c478bd9Sstevel@tonic-gate *mp->b_rptr = EIO; 1749*7c478bd9Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + sizeof (char); 1750*7c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 1751*7c478bd9Sstevel@tonic-gate mp->b_cont = NULL; 1752*7c478bd9Sstevel@tonic-gate qreply(WR(q), mp); 1753*7c478bd9Sstevel@tonic-gate return (NULL); 1754*7c478bd9Sstevel@tonic-gate } 1755*7c478bd9Sstevel@tonic-gate return (mp); 1756*7c478bd9Sstevel@tonic-gate } 1757*7c478bd9Sstevel@tonic-gate 1758*7c478bd9Sstevel@tonic-gate /* 1759*7c478bd9Sstevel@tonic-gate * ARCFOUR-HMAC-MD5 decrypt 1760*7c478bd9Sstevel@tonic-gate * 1761*7c478bd9Sstevel@tonic-gate * format of ciphertext when using ARCFOUR-HMAC-MD5 1762*7c478bd9Sstevel@tonic-gate * +-----------+------------+------------+ 1763*7c478bd9Sstevel@tonic-gate * | hmac | confounder | msg-data | 1764*7c478bd9Sstevel@tonic-gate * +-----------+------------+------------+ 1765*7c478bd9Sstevel@tonic-gate * 1766*7c478bd9Sstevel@tonic-gate */ 1767*7c478bd9Sstevel@tonic-gate static mblk_t * 1768*7c478bd9Sstevel@tonic-gate arcfour_hmac_md5_decrypt(queue_t *q, struct tmodinfo *tmi, mblk_t *mp, 1769*7c478bd9Sstevel@tonic-gate hash_info_t *hash) 1770*7c478bd9Sstevel@tonic-gate { 1771*7c478bd9Sstevel@tonic-gate int result; 1772*7c478bd9Sstevel@tonic-gate size_t cipherlen; 1773*7c478bd9Sstevel@tonic-gate size_t inlen; 1774*7c478bd9Sstevel@tonic-gate size_t saltlen; 1775*7c478bd9Sstevel@tonic-gate crypto_key_t k1, k2; 1776*7c478bd9Sstevel@tonic-gate crypto_data_t indata; 1777*7c478bd9Sstevel@tonic-gate iovec_t v1; 1778*7c478bd9Sstevel@tonic-gate uchar_t ms_exp[9] = {0xab, 0xab, 0xab, 0xab, 0xab, 1779*7c478bd9Sstevel@tonic-gate 0xab, 0xab, 0xab, 0xab }; 1780*7c478bd9Sstevel@tonic-gate uchar_t k1data[CRYPT_ARCFOUR_KEYBYTES]; 1781*7c478bd9Sstevel@tonic-gate uchar_t k2data[CRYPT_ARCFOUR_KEYBYTES]; 1782*7c478bd9Sstevel@tonic-gate uchar_t cksum[MD5_HASHSIZE]; 1783*7c478bd9Sstevel@tonic-gate uchar_t saltdata[CRYPT_ARCFOUR_KEYBYTES]; 1784*7c478bd9Sstevel@tonic-gate crypto_mechanism_t mech; 1785*7c478bd9Sstevel@tonic-gate int usage; 1786*7c478bd9Sstevel@tonic-gate 1787*7c478bd9Sstevel@tonic-gate /* The usage constant is 1026 for all "old" rcmd mode operations */ 1788*7c478bd9Sstevel@tonic-gate if (tmi->dec_data.option_mask & CRYPTOPT_RCMD_MODE_V1) 1789*7c478bd9Sstevel@tonic-gate usage = RCMDV1_USAGE; 1790*7c478bd9Sstevel@tonic-gate else 1791*7c478bd9Sstevel@tonic-gate usage = ARCFOUR_DECRYPT_USAGE; 1792*7c478bd9Sstevel@tonic-gate 1793*7c478bd9Sstevel@tonic-gate /* 1794*7c478bd9Sstevel@tonic-gate * The size at this point should be the size of 1795*7c478bd9Sstevel@tonic-gate * all the plaintext plus the optional plaintext length 1796*7c478bd9Sstevel@tonic-gate * needed for RCMD V2 mode. There should also be room 1797*7c478bd9Sstevel@tonic-gate * at the head of the mblk for the confounder and hash info. 1798*7c478bd9Sstevel@tonic-gate */ 1799*7c478bd9Sstevel@tonic-gate inlen = (size_t)MBLKL(mp); 1800*7c478bd9Sstevel@tonic-gate 1801*7c478bd9Sstevel@tonic-gate /* 1802*7c478bd9Sstevel@tonic-gate * The cipherlen does not include the HMAC at the 1803*7c478bd9Sstevel@tonic-gate * head of the buffer. 1804*7c478bd9Sstevel@tonic-gate */ 1805*7c478bd9Sstevel@tonic-gate cipherlen = inlen - hash->hash_len; 1806*7c478bd9Sstevel@tonic-gate 1807*7c478bd9Sstevel@tonic-gate ASSERT(MBLKSIZE(mp) >= cipherlen); 1808*7c478bd9Sstevel@tonic-gate if (tmi->dec_data.method == CRYPT_METHOD_ARCFOUR_HMAC_MD5_EXP) { 1809*7c478bd9Sstevel@tonic-gate bcopy(ARCFOUR_EXP_SALT, saltdata, strlen(ARCFOUR_EXP_SALT)); 1810*7c478bd9Sstevel@tonic-gate saltdata[9] = 0; 1811*7c478bd9Sstevel@tonic-gate saltdata[10] = usage & 0xff; 1812*7c478bd9Sstevel@tonic-gate saltdata[11] = (usage >> 8) & 0xff; 1813*7c478bd9Sstevel@tonic-gate saltdata[12] = (usage >> 16) & 0xff; 1814*7c478bd9Sstevel@tonic-gate saltdata[13] = (usage >> 24) & 0xff; 1815*7c478bd9Sstevel@tonic-gate saltlen = 14; 1816*7c478bd9Sstevel@tonic-gate } else { 1817*7c478bd9Sstevel@tonic-gate saltdata[0] = usage & 0xff; 1818*7c478bd9Sstevel@tonic-gate saltdata[1] = (usage >> 8) & 0xff; 1819*7c478bd9Sstevel@tonic-gate saltdata[2] = (usage >> 16) & 0xff; 1820*7c478bd9Sstevel@tonic-gate saltdata[3] = (usage >> 24) & 0xff; 1821*7c478bd9Sstevel@tonic-gate saltlen = 4; 1822*7c478bd9Sstevel@tonic-gate } 1823*7c478bd9Sstevel@tonic-gate /* 1824*7c478bd9Sstevel@tonic-gate * Use the salt value to create a key to be used 1825*7c478bd9Sstevel@tonic-gate * for subsequent HMAC operations. 1826*7c478bd9Sstevel@tonic-gate */ 1827*7c478bd9Sstevel@tonic-gate result = do_hmac(md5_hmac_mech, 1828*7c478bd9Sstevel@tonic-gate tmi->dec_data.ckey, 1829*7c478bd9Sstevel@tonic-gate (char *)saltdata, saltlen, 1830*7c478bd9Sstevel@tonic-gate (char *)k1data, sizeof (k1data)); 1831*7c478bd9Sstevel@tonic-gate if (result != CRYPTO_SUCCESS) { 1832*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 1833*7c478bd9Sstevel@tonic-gate "arcfour_hmac_md5_decrypt: do_hmac(k1)" 1834*7c478bd9Sstevel@tonic-gate "failed - error %0x", result); 1835*7c478bd9Sstevel@tonic-gate goto cleanup; 1836*7c478bd9Sstevel@tonic-gate } 1837*7c478bd9Sstevel@tonic-gate bcopy(k1data, k2data, sizeof (k1data)); 1838*7c478bd9Sstevel@tonic-gate 1839*7c478bd9Sstevel@tonic-gate /* 1840*7c478bd9Sstevel@tonic-gate * For the neutered MS RC4 encryption type, 1841*7c478bd9Sstevel@tonic-gate * set the trailing 9 bytes to 0xab per the 1842*7c478bd9Sstevel@tonic-gate * RC4-HMAC spec. 1843*7c478bd9Sstevel@tonic-gate */ 1844*7c478bd9Sstevel@tonic-gate if (tmi->dec_data.method == CRYPT_METHOD_ARCFOUR_HMAC_MD5_EXP) { 1845*7c478bd9Sstevel@tonic-gate bcopy((void *)&k1data[7], ms_exp, sizeof (ms_exp)); 1846*7c478bd9Sstevel@tonic-gate } 1847*7c478bd9Sstevel@tonic-gate 1848*7c478bd9Sstevel@tonic-gate mech.cm_type = tmi->dec_data.mech_type; 1849*7c478bd9Sstevel@tonic-gate mech.cm_param = NULL; 1850*7c478bd9Sstevel@tonic-gate mech.cm_param_len = 0; 1851*7c478bd9Sstevel@tonic-gate 1852*7c478bd9Sstevel@tonic-gate /* 1853*7c478bd9Sstevel@tonic-gate * If we have not yet initialized the decryption key, 1854*7c478bd9Sstevel@tonic-gate * context, and template, do it now. 1855*7c478bd9Sstevel@tonic-gate */ 1856*7c478bd9Sstevel@tonic-gate if (tmi->dec_data.ctx == NULL || 1857*7c478bd9Sstevel@tonic-gate (tmi->dec_data.option_mask & CRYPTOPT_RCMD_MODE_V1)) { 1858*7c478bd9Sstevel@tonic-gate k1.ck_format = CRYPTO_KEY_RAW; 1859*7c478bd9Sstevel@tonic-gate k1.ck_length = CRYPT_ARCFOUR_KEYBYTES * 8; 1860*7c478bd9Sstevel@tonic-gate k1.ck_data = k1data; 1861*7c478bd9Sstevel@tonic-gate 1862*7c478bd9Sstevel@tonic-gate tmi->dec_data.d_encr_key.ck_format = CRYPTO_KEY_RAW; 1863*7c478bd9Sstevel@tonic-gate tmi->dec_data.d_encr_key.ck_length = k1.ck_length; 1864*7c478bd9Sstevel@tonic-gate if (tmi->dec_data.d_encr_key.ck_data == NULL) 1865*7c478bd9Sstevel@tonic-gate tmi->dec_data.d_encr_key.ck_data = kmem_zalloc( 1866*7c478bd9Sstevel@tonic-gate CRYPT_ARCFOUR_KEYBYTES, KM_SLEEP); 1867*7c478bd9Sstevel@tonic-gate 1868*7c478bd9Sstevel@tonic-gate /* 1869*7c478bd9Sstevel@tonic-gate * HMAC operation creates the encryption 1870*7c478bd9Sstevel@tonic-gate * key to be used for the decrypt operations. 1871*7c478bd9Sstevel@tonic-gate */ 1872*7c478bd9Sstevel@tonic-gate result = do_hmac(md5_hmac_mech, &k1, 1873*7c478bd9Sstevel@tonic-gate (char *)mp->b_rptr, hash->hash_len, 1874*7c478bd9Sstevel@tonic-gate (char *)tmi->dec_data.d_encr_key.ck_data, 1875*7c478bd9Sstevel@tonic-gate CRYPT_ARCFOUR_KEYBYTES); 1876*7c478bd9Sstevel@tonic-gate 1877*7c478bd9Sstevel@tonic-gate 1878*7c478bd9Sstevel@tonic-gate if (result != CRYPTO_SUCCESS) { 1879*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 1880*7c478bd9Sstevel@tonic-gate "arcfour_hmac_md5_decrypt: do_hmac(k3)" 1881*7c478bd9Sstevel@tonic-gate "failed - error %0x", result); 1882*7c478bd9Sstevel@tonic-gate goto cleanup; 1883*7c478bd9Sstevel@tonic-gate } 1884*7c478bd9Sstevel@tonic-gate } 1885*7c478bd9Sstevel@tonic-gate 1886*7c478bd9Sstevel@tonic-gate tmi->dec_data.enc_tmpl = NULL; 1887*7c478bd9Sstevel@tonic-gate 1888*7c478bd9Sstevel@tonic-gate if (tmi->dec_data.ctx == NULL && 1889*7c478bd9Sstevel@tonic-gate (tmi->dec_data.option_mask & CRYPTOPT_RCMD_MODE_V2)) { 1890*7c478bd9Sstevel@tonic-gate /* 1891*7c478bd9Sstevel@tonic-gate * Only create a template if we are doing 1892*7c478bd9Sstevel@tonic-gate * chaining from block to block. 1893*7c478bd9Sstevel@tonic-gate */ 1894*7c478bd9Sstevel@tonic-gate result = crypto_create_ctx_template(&mech, 1895*7c478bd9Sstevel@tonic-gate &tmi->dec_data.d_encr_key, 1896*7c478bd9Sstevel@tonic-gate &tmi->dec_data.enc_tmpl, 1897*7c478bd9Sstevel@tonic-gate KM_SLEEP); 1898*7c478bd9Sstevel@tonic-gate if (result == CRYPTO_NOT_SUPPORTED) { 1899*7c478bd9Sstevel@tonic-gate tmi->dec_data.enc_tmpl = NULL; 1900*7c478bd9Sstevel@tonic-gate } else if (result != CRYPTO_SUCCESS) { 1901*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 1902*7c478bd9Sstevel@tonic-gate "arcfour_hmac_md5_decrypt: " 1903*7c478bd9Sstevel@tonic-gate "failed to create dec template " 1904*7c478bd9Sstevel@tonic-gate "for RC4 encrypt: %0x", result); 1905*7c478bd9Sstevel@tonic-gate goto cleanup; 1906*7c478bd9Sstevel@tonic-gate } 1907*7c478bd9Sstevel@tonic-gate 1908*7c478bd9Sstevel@tonic-gate result = crypto_decrypt_init(&mech, 1909*7c478bd9Sstevel@tonic-gate &tmi->dec_data.d_encr_key, 1910*7c478bd9Sstevel@tonic-gate tmi->dec_data.enc_tmpl, 1911*7c478bd9Sstevel@tonic-gate &tmi->dec_data.ctx, NULL); 1912*7c478bd9Sstevel@tonic-gate 1913*7c478bd9Sstevel@tonic-gate if (result != CRYPTO_SUCCESS) { 1914*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "crypto_decrypt_init failed:" 1915*7c478bd9Sstevel@tonic-gate " %0x", result); 1916*7c478bd9Sstevel@tonic-gate goto cleanup; 1917*7c478bd9Sstevel@tonic-gate } 1918*7c478bd9Sstevel@tonic-gate } 1919*7c478bd9Sstevel@tonic-gate 1920*7c478bd9Sstevel@tonic-gate /* adjust the rptr so we don't decrypt the original hmac field */ 1921*7c478bd9Sstevel@tonic-gate 1922*7c478bd9Sstevel@tonic-gate v1.iov_base = (char *)mp->b_rptr + hash->hash_len; 1923*7c478bd9Sstevel@tonic-gate v1.iov_len = cipherlen; 1924*7c478bd9Sstevel@tonic-gate 1925*7c478bd9Sstevel@tonic-gate indata.cd_format = CRYPTO_DATA_RAW; 1926*7c478bd9Sstevel@tonic-gate indata.cd_offset = 0; 1927*7c478bd9Sstevel@tonic-gate indata.cd_length = cipherlen; 1928*7c478bd9Sstevel@tonic-gate indata.cd_raw = v1; 1929*7c478bd9Sstevel@tonic-gate 1930*7c478bd9Sstevel@tonic-gate if (tmi->dec_data.option_mask & CRYPTOPT_RCMD_MODE_V2) 1931*7c478bd9Sstevel@tonic-gate result = crypto_decrypt_update(tmi->dec_data.ctx, 1932*7c478bd9Sstevel@tonic-gate &indata, NULL, NULL); 1933*7c478bd9Sstevel@tonic-gate else 1934*7c478bd9Sstevel@tonic-gate result = crypto_decrypt(&mech, &indata, 1935*7c478bd9Sstevel@tonic-gate &tmi->dec_data.d_encr_key, NULL, NULL, NULL); 1936*7c478bd9Sstevel@tonic-gate 1937*7c478bd9Sstevel@tonic-gate if (result != CRYPTO_SUCCESS) { 1938*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "crypto_decrypt_update failed:" 1939*7c478bd9Sstevel@tonic-gate " %0x", result); 1940*7c478bd9Sstevel@tonic-gate goto cleanup; 1941*7c478bd9Sstevel@tonic-gate } 1942*7c478bd9Sstevel@tonic-gate 1943*7c478bd9Sstevel@tonic-gate k2.ck_format = CRYPTO_KEY_RAW; 1944*7c478bd9Sstevel@tonic-gate k2.ck_length = sizeof (k2data) * 8; 1945*7c478bd9Sstevel@tonic-gate k2.ck_data = k2data; 1946*7c478bd9Sstevel@tonic-gate 1947*7c478bd9Sstevel@tonic-gate result = do_hmac(md5_hmac_mech, 1948*7c478bd9Sstevel@tonic-gate &k2, 1949*7c478bd9Sstevel@tonic-gate (char *)mp->b_rptr + hash->hash_len, cipherlen, 1950*7c478bd9Sstevel@tonic-gate (char *)cksum, hash->hash_len); 1951*7c478bd9Sstevel@tonic-gate 1952*7c478bd9Sstevel@tonic-gate if (result != CRYPTO_SUCCESS) { 1953*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 1954*7c478bd9Sstevel@tonic-gate "arcfour_hmac_md5_decrypt: do_hmac(k2)" 1955*7c478bd9Sstevel@tonic-gate "failed - error %0x", result); 1956*7c478bd9Sstevel@tonic-gate goto cleanup; 1957*7c478bd9Sstevel@tonic-gate } 1958*7c478bd9Sstevel@tonic-gate 1959*7c478bd9Sstevel@tonic-gate if (bcmp(cksum, mp->b_rptr, hash->hash_len) != 0) { 1960*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "arcfour_decrypt HMAC comparison failed"); 1961*7c478bd9Sstevel@tonic-gate result = -1; 1962*7c478bd9Sstevel@tonic-gate goto cleanup; 1963*7c478bd9Sstevel@tonic-gate } 1964*7c478bd9Sstevel@tonic-gate 1965*7c478bd9Sstevel@tonic-gate /* 1966*7c478bd9Sstevel@tonic-gate * adjust the start of the mblk to skip over the 1967*7c478bd9Sstevel@tonic-gate * hash and confounder. 1968*7c478bd9Sstevel@tonic-gate */ 1969*7c478bd9Sstevel@tonic-gate mp->b_rptr += hash->hash_len + hash->confound_len; 1970*7c478bd9Sstevel@tonic-gate 1971*7c478bd9Sstevel@tonic-gate cleanup: 1972*7c478bd9Sstevel@tonic-gate bzero(k1data, sizeof (k1data)); 1973*7c478bd9Sstevel@tonic-gate bzero(k2data, sizeof (k2data)); 1974*7c478bd9Sstevel@tonic-gate bzero(cksum, sizeof (cksum)); 1975*7c478bd9Sstevel@tonic-gate bzero(saltdata, sizeof (saltdata)); 1976*7c478bd9Sstevel@tonic-gate if (result != CRYPTO_SUCCESS) { 1977*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_ERROR; 1978*7c478bd9Sstevel@tonic-gate mp->b_rptr = mp->b_datap->db_base; 1979*7c478bd9Sstevel@tonic-gate *mp->b_rptr = EIO; 1980*7c478bd9Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + sizeof (char); 1981*7c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 1982*7c478bd9Sstevel@tonic-gate mp->b_cont = NULL; 1983*7c478bd9Sstevel@tonic-gate qreply(WR(q), mp); 1984*7c478bd9Sstevel@tonic-gate return (NULL); 1985*7c478bd9Sstevel@tonic-gate } 1986*7c478bd9Sstevel@tonic-gate return (mp); 1987*7c478bd9Sstevel@tonic-gate } 1988*7c478bd9Sstevel@tonic-gate 1989*7c478bd9Sstevel@tonic-gate /* 1990*7c478bd9Sstevel@tonic-gate * ARCFOUR-HMAC-MD5 encrypt 1991*7c478bd9Sstevel@tonic-gate * 1992*7c478bd9Sstevel@tonic-gate * format of ciphertext when using ARCFOUR-HMAC-MD5 1993*7c478bd9Sstevel@tonic-gate * +-----------+------------+------------+ 1994*7c478bd9Sstevel@tonic-gate * | hmac | confounder | msg-data | 1995*7c478bd9Sstevel@tonic-gate * +-----------+------------+------------+ 1996*7c478bd9Sstevel@tonic-gate * 1997*7c478bd9Sstevel@tonic-gate */ 1998*7c478bd9Sstevel@tonic-gate static mblk_t * 1999*7c478bd9Sstevel@tonic-gate arcfour_hmac_md5_encrypt(queue_t *q, struct tmodinfo *tmi, mblk_t *mp, 2000*7c478bd9Sstevel@tonic-gate hash_info_t *hash) 2001*7c478bd9Sstevel@tonic-gate { 2002*7c478bd9Sstevel@tonic-gate int result; 2003*7c478bd9Sstevel@tonic-gate size_t cipherlen; 2004*7c478bd9Sstevel@tonic-gate size_t inlen; 2005*7c478bd9Sstevel@tonic-gate size_t saltlen; 2006*7c478bd9Sstevel@tonic-gate crypto_key_t k1, k2; 2007*7c478bd9Sstevel@tonic-gate crypto_data_t indata; 2008*7c478bd9Sstevel@tonic-gate iovec_t v1; 2009*7c478bd9Sstevel@tonic-gate uchar_t ms_exp[9] = {0xab, 0xab, 0xab, 0xab, 0xab, 2010*7c478bd9Sstevel@tonic-gate 0xab, 0xab, 0xab, 0xab }; 2011*7c478bd9Sstevel@tonic-gate uchar_t k1data[CRYPT_ARCFOUR_KEYBYTES]; 2012*7c478bd9Sstevel@tonic-gate uchar_t k2data[CRYPT_ARCFOUR_KEYBYTES]; 2013*7c478bd9Sstevel@tonic-gate uchar_t saltdata[CRYPT_ARCFOUR_KEYBYTES]; 2014*7c478bd9Sstevel@tonic-gate crypto_mechanism_t mech; 2015*7c478bd9Sstevel@tonic-gate int usage; 2016*7c478bd9Sstevel@tonic-gate 2017*7c478bd9Sstevel@tonic-gate /* The usage constant is 1026 for all "old" rcmd mode operations */ 2018*7c478bd9Sstevel@tonic-gate if (tmi->enc_data.option_mask & CRYPTOPT_RCMD_MODE_V1) 2019*7c478bd9Sstevel@tonic-gate usage = RCMDV1_USAGE; 2020*7c478bd9Sstevel@tonic-gate else 2021*7c478bd9Sstevel@tonic-gate usage = ARCFOUR_ENCRYPT_USAGE; 2022*7c478bd9Sstevel@tonic-gate 2023*7c478bd9Sstevel@tonic-gate mech.cm_type = tmi->enc_data.mech_type; 2024*7c478bd9Sstevel@tonic-gate mech.cm_param = NULL; 2025*7c478bd9Sstevel@tonic-gate mech.cm_param_len = 0; 2026*7c478bd9Sstevel@tonic-gate 2027*7c478bd9Sstevel@tonic-gate /* 2028*7c478bd9Sstevel@tonic-gate * The size at this point should be the size of 2029*7c478bd9Sstevel@tonic-gate * all the plaintext plus the optional plaintext length 2030*7c478bd9Sstevel@tonic-gate * needed for RCMD V2 mode. There should also be room 2031*7c478bd9Sstevel@tonic-gate * at the head of the mblk for the confounder and hash info. 2032*7c478bd9Sstevel@tonic-gate */ 2033*7c478bd9Sstevel@tonic-gate inlen = (size_t)MBLKL(mp); 2034*7c478bd9Sstevel@tonic-gate 2035*7c478bd9Sstevel@tonic-gate cipherlen = encrypt_size(&tmi->enc_data, inlen); 2036*7c478bd9Sstevel@tonic-gate 2037*7c478bd9Sstevel@tonic-gate ASSERT(MBLKSIZE(mp) >= cipherlen); 2038*7c478bd9Sstevel@tonic-gate 2039*7c478bd9Sstevel@tonic-gate /* 2040*7c478bd9Sstevel@tonic-gate * Shift the rptr back enough to insert 2041*7c478bd9Sstevel@tonic-gate * the confounder and hash. 2042*7c478bd9Sstevel@tonic-gate */ 2043*7c478bd9Sstevel@tonic-gate mp->b_rptr -= (hash->confound_len + hash->hash_len); 2044*7c478bd9Sstevel@tonic-gate 2045*7c478bd9Sstevel@tonic-gate /* zero out the hash area */ 2046*7c478bd9Sstevel@tonic-gate bzero(mp->b_rptr, (size_t)hash->hash_len); 2047*7c478bd9Sstevel@tonic-gate 2048*7c478bd9Sstevel@tonic-gate if (cipherlen > inlen) { 2049*7c478bd9Sstevel@tonic-gate bzero(mp->b_wptr, MBLKTAIL(mp)); 2050*7c478bd9Sstevel@tonic-gate } 2051*7c478bd9Sstevel@tonic-gate 2052*7c478bd9Sstevel@tonic-gate if (tmi->enc_data.method == CRYPT_METHOD_ARCFOUR_HMAC_MD5_EXP) { 2053*7c478bd9Sstevel@tonic-gate bcopy(ARCFOUR_EXP_SALT, saltdata, strlen(ARCFOUR_EXP_SALT)); 2054*7c478bd9Sstevel@tonic-gate saltdata[9] = 0; 2055*7c478bd9Sstevel@tonic-gate saltdata[10] = usage & 0xff; 2056*7c478bd9Sstevel@tonic-gate saltdata[11] = (usage >> 8) & 0xff; 2057*7c478bd9Sstevel@tonic-gate saltdata[12] = (usage >> 16) & 0xff; 2058*7c478bd9Sstevel@tonic-gate saltdata[13] = (usage >> 24) & 0xff; 2059*7c478bd9Sstevel@tonic-gate saltlen = 14; 2060*7c478bd9Sstevel@tonic-gate } else { 2061*7c478bd9Sstevel@tonic-gate saltdata[0] = usage & 0xff; 2062*7c478bd9Sstevel@tonic-gate saltdata[1] = (usage >> 8) & 0xff; 2063*7c478bd9Sstevel@tonic-gate saltdata[2] = (usage >> 16) & 0xff; 2064*7c478bd9Sstevel@tonic-gate saltdata[3] = (usage >> 24) & 0xff; 2065*7c478bd9Sstevel@tonic-gate saltlen = 4; 2066*7c478bd9Sstevel@tonic-gate } 2067*7c478bd9Sstevel@tonic-gate /* 2068*7c478bd9Sstevel@tonic-gate * Use the salt value to create a key to be used 2069*7c478bd9Sstevel@tonic-gate * for subsequent HMAC operations. 2070*7c478bd9Sstevel@tonic-gate */ 2071*7c478bd9Sstevel@tonic-gate result = do_hmac(md5_hmac_mech, 2072*7c478bd9Sstevel@tonic-gate tmi->enc_data.ckey, 2073*7c478bd9Sstevel@tonic-gate (char *)saltdata, saltlen, 2074*7c478bd9Sstevel@tonic-gate (char *)k1data, sizeof (k1data)); 2075*7c478bd9Sstevel@tonic-gate if (result != CRYPTO_SUCCESS) { 2076*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 2077*7c478bd9Sstevel@tonic-gate "arcfour_hmac_md5_encrypt: do_hmac(k1)" 2078*7c478bd9Sstevel@tonic-gate "failed - error %0x", result); 2079*7c478bd9Sstevel@tonic-gate goto cleanup; 2080*7c478bd9Sstevel@tonic-gate } 2081*7c478bd9Sstevel@tonic-gate 2082*7c478bd9Sstevel@tonic-gate bcopy(k1data, k2data, sizeof (k2data)); 2083*7c478bd9Sstevel@tonic-gate 2084*7c478bd9Sstevel@tonic-gate /* 2085*7c478bd9Sstevel@tonic-gate * For the neutered MS RC4 encryption type, 2086*7c478bd9Sstevel@tonic-gate * set the trailing 9 bytes to 0xab per the 2087*7c478bd9Sstevel@tonic-gate * RC4-HMAC spec. 2088*7c478bd9Sstevel@tonic-gate */ 2089*7c478bd9Sstevel@tonic-gate if (tmi->enc_data.method == CRYPT_METHOD_ARCFOUR_HMAC_MD5_EXP) { 2090*7c478bd9Sstevel@tonic-gate bcopy((void *)&k1data[7], ms_exp, sizeof (ms_exp)); 2091*7c478bd9Sstevel@tonic-gate } 2092*7c478bd9Sstevel@tonic-gate 2093*7c478bd9Sstevel@tonic-gate /* 2094*7c478bd9Sstevel@tonic-gate * Get the confounder bytes. 2095*7c478bd9Sstevel@tonic-gate */ 2096*7c478bd9Sstevel@tonic-gate (void) random_get_pseudo_bytes( 2097*7c478bd9Sstevel@tonic-gate (uint8_t *)(mp->b_rptr + hash->hash_len), 2098*7c478bd9Sstevel@tonic-gate (size_t)hash->confound_len); 2099*7c478bd9Sstevel@tonic-gate 2100*7c478bd9Sstevel@tonic-gate k2.ck_data = k2data; 2101*7c478bd9Sstevel@tonic-gate k2.ck_format = CRYPTO_KEY_RAW; 2102*7c478bd9Sstevel@tonic-gate k2.ck_length = sizeof (k2data) * 8; 2103*7c478bd9Sstevel@tonic-gate 2104*7c478bd9Sstevel@tonic-gate /* 2105*7c478bd9Sstevel@tonic-gate * This writes the HMAC to the hash area in the 2106*7c478bd9Sstevel@tonic-gate * mblk. The key used is the one just created by 2107*7c478bd9Sstevel@tonic-gate * the previous HMAC operation. 2108*7c478bd9Sstevel@tonic-gate * The data being processed is the confounder bytes 2109*7c478bd9Sstevel@tonic-gate * PLUS the input plaintext. 2110*7c478bd9Sstevel@tonic-gate */ 2111*7c478bd9Sstevel@tonic-gate result = do_hmac(md5_hmac_mech, &k2, 2112*7c478bd9Sstevel@tonic-gate (char *)mp->b_rptr + hash->hash_len, 2113*7c478bd9Sstevel@tonic-gate hash->confound_len + inlen, 2114*7c478bd9Sstevel@tonic-gate (char *)mp->b_rptr, hash->hash_len); 2115*7c478bd9Sstevel@tonic-gate if (result != CRYPTO_SUCCESS) { 2116*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 2117*7c478bd9Sstevel@tonic-gate "arcfour_hmac_md5_encrypt: do_hmac(k2)" 2118*7c478bd9Sstevel@tonic-gate "failed - error %0x", result); 2119*7c478bd9Sstevel@tonic-gate goto cleanup; 2120*7c478bd9Sstevel@tonic-gate } 2121*7c478bd9Sstevel@tonic-gate /* 2122*7c478bd9Sstevel@tonic-gate * Because of the odd way that MIT uses RC4 keys 2123*7c478bd9Sstevel@tonic-gate * on the rlogin stream, we only need to create 2124*7c478bd9Sstevel@tonic-gate * this key once. 2125*7c478bd9Sstevel@tonic-gate * However, if using "old" rcmd mode, we need to do 2126*7c478bd9Sstevel@tonic-gate * it every time. 2127*7c478bd9Sstevel@tonic-gate */ 2128*7c478bd9Sstevel@tonic-gate if (tmi->enc_data.ctx == NULL || 2129*7c478bd9Sstevel@tonic-gate (tmi->enc_data.option_mask & CRYPTOPT_RCMD_MODE_V1)) { 2130*7c478bd9Sstevel@tonic-gate crypto_key_t *key = &tmi->enc_data.d_encr_key; 2131*7c478bd9Sstevel@tonic-gate 2132*7c478bd9Sstevel@tonic-gate k1.ck_data = k1data; 2133*7c478bd9Sstevel@tonic-gate k1.ck_format = CRYPTO_KEY_RAW; 2134*7c478bd9Sstevel@tonic-gate k1.ck_length = sizeof (k1data) * 8; 2135*7c478bd9Sstevel@tonic-gate 2136*7c478bd9Sstevel@tonic-gate key->ck_format = CRYPTO_KEY_RAW; 2137*7c478bd9Sstevel@tonic-gate key->ck_length = k1.ck_length; 2138*7c478bd9Sstevel@tonic-gate if (key->ck_data == NULL) 2139*7c478bd9Sstevel@tonic-gate key->ck_data = kmem_zalloc( 2140*7c478bd9Sstevel@tonic-gate CRYPT_ARCFOUR_KEYBYTES, KM_SLEEP); 2141*7c478bd9Sstevel@tonic-gate 2142*7c478bd9Sstevel@tonic-gate /* 2143*7c478bd9Sstevel@tonic-gate * The final HMAC operation creates the encryption 2144*7c478bd9Sstevel@tonic-gate * key to be used for the encrypt operation. 2145*7c478bd9Sstevel@tonic-gate */ 2146*7c478bd9Sstevel@tonic-gate result = do_hmac(md5_hmac_mech, &k1, 2147*7c478bd9Sstevel@tonic-gate (char *)mp->b_rptr, hash->hash_len, 2148*7c478bd9Sstevel@tonic-gate (char *)key->ck_data, CRYPT_ARCFOUR_KEYBYTES); 2149*7c478bd9Sstevel@tonic-gate 2150*7c478bd9Sstevel@tonic-gate if (result != CRYPTO_SUCCESS) { 2151*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 2152*7c478bd9Sstevel@tonic-gate "arcfour_hmac_md5_encrypt: do_hmac(k3)" 2153*7c478bd9Sstevel@tonic-gate "failed - error %0x", result); 2154*7c478bd9Sstevel@tonic-gate goto cleanup; 2155*7c478bd9Sstevel@tonic-gate } 2156*7c478bd9Sstevel@tonic-gate } 2157*7c478bd9Sstevel@tonic-gate 2158*7c478bd9Sstevel@tonic-gate /* 2159*7c478bd9Sstevel@tonic-gate * If the context has not been initialized, do it now. 2160*7c478bd9Sstevel@tonic-gate */ 2161*7c478bd9Sstevel@tonic-gate if (tmi->enc_data.ctx == NULL && 2162*7c478bd9Sstevel@tonic-gate (tmi->enc_data.option_mask & CRYPTOPT_RCMD_MODE_V2)) { 2163*7c478bd9Sstevel@tonic-gate /* 2164*7c478bd9Sstevel@tonic-gate * Only create a template if we are doing 2165*7c478bd9Sstevel@tonic-gate * chaining from block to block. 2166*7c478bd9Sstevel@tonic-gate */ 2167*7c478bd9Sstevel@tonic-gate result = crypto_create_ctx_template(&mech, 2168*7c478bd9Sstevel@tonic-gate &tmi->enc_data.d_encr_key, 2169*7c478bd9Sstevel@tonic-gate &tmi->enc_data.enc_tmpl, 2170*7c478bd9Sstevel@tonic-gate KM_SLEEP); 2171*7c478bd9Sstevel@tonic-gate if (result == CRYPTO_NOT_SUPPORTED) { 2172*7c478bd9Sstevel@tonic-gate tmi->enc_data.enc_tmpl = NULL; 2173*7c478bd9Sstevel@tonic-gate } else if (result != CRYPTO_SUCCESS) { 2174*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "failed to create enc template " 2175*7c478bd9Sstevel@tonic-gate "for RC4 encrypt: %0x", result); 2176*7c478bd9Sstevel@tonic-gate goto cleanup; 2177*7c478bd9Sstevel@tonic-gate } 2178*7c478bd9Sstevel@tonic-gate 2179*7c478bd9Sstevel@tonic-gate result = crypto_encrypt_init(&mech, 2180*7c478bd9Sstevel@tonic-gate &tmi->enc_data.d_encr_key, 2181*7c478bd9Sstevel@tonic-gate tmi->enc_data.enc_tmpl, 2182*7c478bd9Sstevel@tonic-gate &tmi->enc_data.ctx, NULL); 2183*7c478bd9Sstevel@tonic-gate if (result != CRYPTO_SUCCESS) { 2184*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "crypto_encrypt_init failed:" 2185*7c478bd9Sstevel@tonic-gate " %0x", result); 2186*7c478bd9Sstevel@tonic-gate goto cleanup; 2187*7c478bd9Sstevel@tonic-gate } 2188*7c478bd9Sstevel@tonic-gate } 2189*7c478bd9Sstevel@tonic-gate v1.iov_base = (char *)mp->b_rptr + hash->hash_len; 2190*7c478bd9Sstevel@tonic-gate v1.iov_len = hash->confound_len + inlen; 2191*7c478bd9Sstevel@tonic-gate 2192*7c478bd9Sstevel@tonic-gate indata.cd_format = CRYPTO_DATA_RAW; 2193*7c478bd9Sstevel@tonic-gate indata.cd_offset = 0; 2194*7c478bd9Sstevel@tonic-gate indata.cd_length = hash->confound_len + inlen; 2195*7c478bd9Sstevel@tonic-gate indata.cd_raw = v1; 2196*7c478bd9Sstevel@tonic-gate 2197*7c478bd9Sstevel@tonic-gate if (tmi->enc_data.option_mask & CRYPTOPT_RCMD_MODE_V2) 2198*7c478bd9Sstevel@tonic-gate result = crypto_encrypt_update(tmi->enc_data.ctx, 2199*7c478bd9Sstevel@tonic-gate &indata, NULL, NULL); 2200*7c478bd9Sstevel@tonic-gate else 2201*7c478bd9Sstevel@tonic-gate result = crypto_encrypt(&mech, &indata, 2202*7c478bd9Sstevel@tonic-gate &tmi->enc_data.d_encr_key, NULL, 2203*7c478bd9Sstevel@tonic-gate NULL, NULL); 2204*7c478bd9Sstevel@tonic-gate 2205*7c478bd9Sstevel@tonic-gate if (result != CRYPTO_SUCCESS) { 2206*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "crypto_encrypt_update failed: 0x%0x", 2207*7c478bd9Sstevel@tonic-gate result); 2208*7c478bd9Sstevel@tonic-gate } 2209*7c478bd9Sstevel@tonic-gate 2210*7c478bd9Sstevel@tonic-gate cleanup: 2211*7c478bd9Sstevel@tonic-gate bzero(k1data, sizeof (k1data)); 2212*7c478bd9Sstevel@tonic-gate bzero(k2data, sizeof (k2data)); 2213*7c478bd9Sstevel@tonic-gate bzero(saltdata, sizeof (saltdata)); 2214*7c478bd9Sstevel@tonic-gate if (result != CRYPTO_SUCCESS) { 2215*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_ERROR; 2216*7c478bd9Sstevel@tonic-gate mp->b_rptr = mp->b_datap->db_base; 2217*7c478bd9Sstevel@tonic-gate *mp->b_rptr = EIO; 2218*7c478bd9Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + sizeof (char); 2219*7c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 2220*7c478bd9Sstevel@tonic-gate mp->b_cont = NULL; 2221*7c478bd9Sstevel@tonic-gate qreply(WR(q), mp); 2222*7c478bd9Sstevel@tonic-gate return (NULL); 2223*7c478bd9Sstevel@tonic-gate } 2224*7c478bd9Sstevel@tonic-gate return (mp); 2225*7c478bd9Sstevel@tonic-gate } 2226*7c478bd9Sstevel@tonic-gate 2227*7c478bd9Sstevel@tonic-gate /* 2228*7c478bd9Sstevel@tonic-gate * DES-CBC-[HASH] encrypt 2229*7c478bd9Sstevel@tonic-gate * 2230*7c478bd9Sstevel@tonic-gate * Needed to support userland apps that must support Kerberos V5 2231*7c478bd9Sstevel@tonic-gate * encryption DES-CBC encryption modes. 2232*7c478bd9Sstevel@tonic-gate * 2233*7c478bd9Sstevel@tonic-gate * The HASH values supported are RAW(NULL), MD5, CRC32, and SHA1 2234*7c478bd9Sstevel@tonic-gate * 2235*7c478bd9Sstevel@tonic-gate * format of ciphertext for DES-CBC functions, per RFC1510 is: 2236*7c478bd9Sstevel@tonic-gate * +-----------+----------+-------------+-----+ 2237*7c478bd9Sstevel@tonic-gate * |confounder | cksum | msg-data | pad | 2238*7c478bd9Sstevel@tonic-gate * +-----------+----------+-------------+-----+ 2239*7c478bd9Sstevel@tonic-gate * 2240*7c478bd9Sstevel@tonic-gate * format of ciphertext when using DES3-SHA1-HMAC 2241*7c478bd9Sstevel@tonic-gate * +-----------+----------+-------------+-----+ 2242*7c478bd9Sstevel@tonic-gate * |confounder | msg-data | hmac | pad | 2243*7c478bd9Sstevel@tonic-gate * +-----------+----------+-------------+-----+ 2244*7c478bd9Sstevel@tonic-gate * 2245*7c478bd9Sstevel@tonic-gate * The confounder is 8 bytes of random data. 2246*7c478bd9Sstevel@tonic-gate * The cksum depends on the hash being used. 2247*7c478bd9Sstevel@tonic-gate * 4 bytes for CRC32 2248*7c478bd9Sstevel@tonic-gate * 16 bytes for MD5 2249*7c478bd9Sstevel@tonic-gate * 20 bytes for SHA1 2250*7c478bd9Sstevel@tonic-gate * 0 bytes for RAW 2251*7c478bd9Sstevel@tonic-gate * 2252*7c478bd9Sstevel@tonic-gate */ 2253*7c478bd9Sstevel@tonic-gate static mblk_t * 2254*7c478bd9Sstevel@tonic-gate des_cbc_encrypt(queue_t *q, struct tmodinfo *tmi, mblk_t *mp, hash_info_t *hash) 2255*7c478bd9Sstevel@tonic-gate { 2256*7c478bd9Sstevel@tonic-gate int result; 2257*7c478bd9Sstevel@tonic-gate size_t cipherlen; 2258*7c478bd9Sstevel@tonic-gate size_t inlen; 2259*7c478bd9Sstevel@tonic-gate size_t plainlen; 2260*7c478bd9Sstevel@tonic-gate 2261*7c478bd9Sstevel@tonic-gate /* 2262*7c478bd9Sstevel@tonic-gate * The size at this point should be the size of 2263*7c478bd9Sstevel@tonic-gate * all the plaintext plus the optional plaintext length 2264*7c478bd9Sstevel@tonic-gate * needed for RCMD V2 mode. There should also be room 2265*7c478bd9Sstevel@tonic-gate * at the head of the mblk for the confounder and hash info. 2266*7c478bd9Sstevel@tonic-gate */ 2267*7c478bd9Sstevel@tonic-gate inlen = (size_t)MBLKL(mp); 2268*7c478bd9Sstevel@tonic-gate 2269*7c478bd9Sstevel@tonic-gate /* 2270*7c478bd9Sstevel@tonic-gate * The output size will be a multiple of 8 because this algorithm 2271*7c478bd9Sstevel@tonic-gate * only works on 8 byte chunks. 2272*7c478bd9Sstevel@tonic-gate */ 2273*7c478bd9Sstevel@tonic-gate cipherlen = encrypt_size(&tmi->enc_data, inlen); 2274*7c478bd9Sstevel@tonic-gate 2275*7c478bd9Sstevel@tonic-gate ASSERT(MBLKSIZE(mp) >= cipherlen); 2276*7c478bd9Sstevel@tonic-gate 2277*7c478bd9Sstevel@tonic-gate if (cipherlen > inlen) { 2278*7c478bd9Sstevel@tonic-gate bzero(mp->b_wptr, MBLKTAIL(mp)); 2279*7c478bd9Sstevel@tonic-gate } 2280*7c478bd9Sstevel@tonic-gate 2281*7c478bd9Sstevel@tonic-gate /* 2282*7c478bd9Sstevel@tonic-gate * Shift the rptr back enough to insert 2283*7c478bd9Sstevel@tonic-gate * the confounder and hash. 2284*7c478bd9Sstevel@tonic-gate */ 2285*7c478bd9Sstevel@tonic-gate if (tmi->enc_data.method == CRYPT_METHOD_DES3_CBC_SHA1) { 2286*7c478bd9Sstevel@tonic-gate mp->b_rptr -= hash->confound_len; 2287*7c478bd9Sstevel@tonic-gate } else { 2288*7c478bd9Sstevel@tonic-gate mp->b_rptr -= (hash->confound_len + hash->hash_len); 2289*7c478bd9Sstevel@tonic-gate 2290*7c478bd9Sstevel@tonic-gate /* zero out the hash area */ 2291*7c478bd9Sstevel@tonic-gate bzero(mp->b_rptr + hash->confound_len, (size_t)hash->hash_len); 2292*7c478bd9Sstevel@tonic-gate } 2293*7c478bd9Sstevel@tonic-gate 2294*7c478bd9Sstevel@tonic-gate /* get random confounder from our friend, the 'random' module */ 2295*7c478bd9Sstevel@tonic-gate if (hash->confound_len > 0) { 2296*7c478bd9Sstevel@tonic-gate (void) random_get_pseudo_bytes((uint8_t *)mp->b_rptr, 2297*7c478bd9Sstevel@tonic-gate (size_t)hash->confound_len); 2298*7c478bd9Sstevel@tonic-gate } 2299*7c478bd9Sstevel@tonic-gate 2300*7c478bd9Sstevel@tonic-gate /* 2301*7c478bd9Sstevel@tonic-gate * For 3DES we calculate an HMAC later. 2302*7c478bd9Sstevel@tonic-gate */ 2303*7c478bd9Sstevel@tonic-gate if (tmi->enc_data.method != CRYPT_METHOD_DES3_CBC_SHA1) { 2304*7c478bd9Sstevel@tonic-gate /* calculate chksum of confounder + input */ 2305*7c478bd9Sstevel@tonic-gate if (hash->hash_len > 0 && hash->hashfunc != NULL) { 2306*7c478bd9Sstevel@tonic-gate uchar_t cksum[MAX_CKSUM_LEN]; 2307*7c478bd9Sstevel@tonic-gate 2308*7c478bd9Sstevel@tonic-gate result = hash->hashfunc(cksum, mp->b_rptr, 2309*7c478bd9Sstevel@tonic-gate cipherlen); 2310*7c478bd9Sstevel@tonic-gate if (result != CRYPTO_SUCCESS) { 2311*7c478bd9Sstevel@tonic-gate goto failure; 2312*7c478bd9Sstevel@tonic-gate } 2313*7c478bd9Sstevel@tonic-gate 2314*7c478bd9Sstevel@tonic-gate /* put hash in place right after the confounder */ 2315*7c478bd9Sstevel@tonic-gate bcopy(cksum, (mp->b_rptr + hash->confound_len), 2316*7c478bd9Sstevel@tonic-gate (size_t)hash->hash_len); 2317*7c478bd9Sstevel@tonic-gate } 2318*7c478bd9Sstevel@tonic-gate } 2319*7c478bd9Sstevel@tonic-gate /* 2320*7c478bd9Sstevel@tonic-gate * In order to support the "old" Kerberos RCMD protocol, 2321*7c478bd9Sstevel@tonic-gate * we must use the IVEC 3 different ways: 2322*7c478bd9Sstevel@tonic-gate * IVEC_REUSE = keep using the same IV each time, this is 2323*7c478bd9Sstevel@tonic-gate * ugly and insecure, but necessary for 2324*7c478bd9Sstevel@tonic-gate * backwards compatibility with existing MIT code. 2325*7c478bd9Sstevel@tonic-gate * IVEC_ONETIME = Use the ivec as initialized when the crypto 2326*7c478bd9Sstevel@tonic-gate * was setup (see setup_crypto routine). 2327*7c478bd9Sstevel@tonic-gate * IVEC_NEVER = never use an IVEC, use a bunch of 0's as the IV (yuk). 2328*7c478bd9Sstevel@tonic-gate */ 2329*7c478bd9Sstevel@tonic-gate if (tmi->enc_data.ivec_usage == IVEC_NEVER) { 2330*7c478bd9Sstevel@tonic-gate bzero(tmi->enc_data.block, tmi->enc_data.blocklen); 2331*7c478bd9Sstevel@tonic-gate } else if (tmi->enc_data.ivec_usage == IVEC_REUSE) { 2332*7c478bd9Sstevel@tonic-gate bcopy(tmi->enc_data.ivec, tmi->enc_data.block, 2333*7c478bd9Sstevel@tonic-gate tmi->enc_data.blocklen); 2334*7c478bd9Sstevel@tonic-gate } 2335*7c478bd9Sstevel@tonic-gate 2336*7c478bd9Sstevel@tonic-gate if (tmi->enc_data.method == CRYPT_METHOD_DES3_CBC_SHA1) { 2337*7c478bd9Sstevel@tonic-gate /* 2338*7c478bd9Sstevel@tonic-gate * The input length already included the hash size, 2339*7c478bd9Sstevel@tonic-gate * don't include this in the plaintext length 2340*7c478bd9Sstevel@tonic-gate * calculations. 2341*7c478bd9Sstevel@tonic-gate */ 2342*7c478bd9Sstevel@tonic-gate plainlen = cipherlen - hash->hash_len; 2343*7c478bd9Sstevel@tonic-gate 2344*7c478bd9Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + plainlen; 2345*7c478bd9Sstevel@tonic-gate 2346*7c478bd9Sstevel@tonic-gate result = kef_encr_hmac(&tmi->enc_data, 2347*7c478bd9Sstevel@tonic-gate (void *)mp, (size_t)plainlen, 2348*7c478bd9Sstevel@tonic-gate (char *)(mp->b_rptr + plainlen), 2349*7c478bd9Sstevel@tonic-gate hash->hash_len); 2350*7c478bd9Sstevel@tonic-gate } else { 2351*7c478bd9Sstevel@tonic-gate ASSERT(mp->b_rptr + cipherlen <= DB_LIM(mp)); 2352*7c478bd9Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + cipherlen; 2353*7c478bd9Sstevel@tonic-gate result = kef_crypt(&tmi->enc_data, (void *)mp, 2354*7c478bd9Sstevel@tonic-gate CRYPTO_DATA_MBLK, (size_t)cipherlen, 2355*7c478bd9Sstevel@tonic-gate CRYPT_ENCRYPT); 2356*7c478bd9Sstevel@tonic-gate } 2357*7c478bd9Sstevel@tonic-gate failure: 2358*7c478bd9Sstevel@tonic-gate if (result != CRYPTO_SUCCESS) { 2359*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 2360*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 2361*7c478bd9Sstevel@tonic-gate "des_cbc_encrypt: kef_crypt encrypt " 2362*7c478bd9Sstevel@tonic-gate "failed (len: %ld) - error %0x", 2363*7c478bd9Sstevel@tonic-gate cipherlen, result); 2364*7c478bd9Sstevel@tonic-gate #endif 2365*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_ERROR; 2366*7c478bd9Sstevel@tonic-gate mp->b_rptr = mp->b_datap->db_base; 2367*7c478bd9Sstevel@tonic-gate *mp->b_rptr = EIO; 2368*7c478bd9Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + sizeof (char); 2369*7c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 2370*7c478bd9Sstevel@tonic-gate mp->b_cont = NULL; 2371*7c478bd9Sstevel@tonic-gate qreply(WR(q), mp); 2372*7c478bd9Sstevel@tonic-gate return (NULL); 2373*7c478bd9Sstevel@tonic-gate } else if (tmi->enc_data.ivec_usage == IVEC_ONETIME) { 2374*7c478bd9Sstevel@tonic-gate /* 2375*7c478bd9Sstevel@tonic-gate * Because we are using KEF, we must manually 2376*7c478bd9Sstevel@tonic-gate * update our IV. 2377*7c478bd9Sstevel@tonic-gate */ 2378*7c478bd9Sstevel@tonic-gate bcopy(mp->b_wptr - tmi->enc_data.ivlen, 2379*7c478bd9Sstevel@tonic-gate tmi->enc_data.block, tmi->enc_data.ivlen); 2380*7c478bd9Sstevel@tonic-gate } 2381*7c478bd9Sstevel@tonic-gate if (tmi->enc_data.method == CRYPT_METHOD_DES3_CBC_SHA1) { 2382*7c478bd9Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + cipherlen; 2383*7c478bd9Sstevel@tonic-gate } 2384*7c478bd9Sstevel@tonic-gate 2385*7c478bd9Sstevel@tonic-gate return (mp); 2386*7c478bd9Sstevel@tonic-gate } 2387*7c478bd9Sstevel@tonic-gate 2388*7c478bd9Sstevel@tonic-gate /* 2389*7c478bd9Sstevel@tonic-gate * des_cbc_decrypt 2390*7c478bd9Sstevel@tonic-gate * 2391*7c478bd9Sstevel@tonic-gate * 2392*7c478bd9Sstevel@tonic-gate * Needed to support userland apps that must support Kerberos V5 2393*7c478bd9Sstevel@tonic-gate * encryption DES-CBC decryption modes. 2394*7c478bd9Sstevel@tonic-gate * 2395*7c478bd9Sstevel@tonic-gate * The HASH values supported are RAW(NULL), MD5, CRC32, and SHA1 2396*7c478bd9Sstevel@tonic-gate * 2397*7c478bd9Sstevel@tonic-gate * format of ciphertext for DES-CBC functions, per RFC1510 is: 2398*7c478bd9Sstevel@tonic-gate * +-----------+----------+-------------+-----+ 2399*7c478bd9Sstevel@tonic-gate * |confounder | cksum | msg-data | pad | 2400*7c478bd9Sstevel@tonic-gate * +-----------+----------+-------------+-----+ 2401*7c478bd9Sstevel@tonic-gate * 2402*7c478bd9Sstevel@tonic-gate * format of ciphertext when using DES3-SHA1-HMAC 2403*7c478bd9Sstevel@tonic-gate * +-----------+----------+-------------+-----+ 2404*7c478bd9Sstevel@tonic-gate * |confounder | msg-data | hmac | pad | 2405*7c478bd9Sstevel@tonic-gate * +-----------+----------+-------------+-----+ 2406*7c478bd9Sstevel@tonic-gate * 2407*7c478bd9Sstevel@tonic-gate * The confounder is 8 bytes of random data. 2408*7c478bd9Sstevel@tonic-gate * The cksum depends on the hash being used. 2409*7c478bd9Sstevel@tonic-gate * 4 bytes for CRC32 2410*7c478bd9Sstevel@tonic-gate * 16 bytes for MD5 2411*7c478bd9Sstevel@tonic-gate * 20 bytes for SHA1 2412*7c478bd9Sstevel@tonic-gate * 0 bytes for RAW 2413*7c478bd9Sstevel@tonic-gate * 2414*7c478bd9Sstevel@tonic-gate */ 2415*7c478bd9Sstevel@tonic-gate static mblk_t * 2416*7c478bd9Sstevel@tonic-gate des_cbc_decrypt(queue_t *q, struct tmodinfo *tmi, mblk_t *mp, hash_info_t *hash) 2417*7c478bd9Sstevel@tonic-gate { 2418*7c478bd9Sstevel@tonic-gate uint_t inlen, datalen; 2419*7c478bd9Sstevel@tonic-gate int result = 0; 2420*7c478bd9Sstevel@tonic-gate uchar_t *optr = NULL; 2421*7c478bd9Sstevel@tonic-gate uchar_t cksum[MAX_CKSUM_LEN], newcksum[MAX_CKSUM_LEN]; 2422*7c478bd9Sstevel@tonic-gate uchar_t nextiv[DEFAULT_DES_BLOCKLEN]; 2423*7c478bd9Sstevel@tonic-gate 2424*7c478bd9Sstevel@tonic-gate /* Compute adjusted size */ 2425*7c478bd9Sstevel@tonic-gate inlen = MBLKL(mp); 2426*7c478bd9Sstevel@tonic-gate 2427*7c478bd9Sstevel@tonic-gate optr = mp->b_rptr; 2428*7c478bd9Sstevel@tonic-gate 2429*7c478bd9Sstevel@tonic-gate /* 2430*7c478bd9Sstevel@tonic-gate * In order to support the "old" Kerberos RCMD protocol, 2431*7c478bd9Sstevel@tonic-gate * we must use the IVEC 3 different ways: 2432*7c478bd9Sstevel@tonic-gate * IVEC_REUSE = keep using the same IV each time, this is 2433*7c478bd9Sstevel@tonic-gate * ugly and insecure, but necessary for 2434*7c478bd9Sstevel@tonic-gate * backwards compatibility with existing MIT code. 2435*7c478bd9Sstevel@tonic-gate * IVEC_ONETIME = Use the ivec as initialized when the crypto 2436*7c478bd9Sstevel@tonic-gate * was setup (see setup_crypto routine). 2437*7c478bd9Sstevel@tonic-gate * IVEC_NEVER = never use an IVEC, use a bunch of 0's as the IV (yuk). 2438*7c478bd9Sstevel@tonic-gate */ 2439*7c478bd9Sstevel@tonic-gate if (tmi->dec_data.ivec_usage == IVEC_NEVER) 2440*7c478bd9Sstevel@tonic-gate bzero(tmi->dec_data.block, tmi->dec_data.blocklen); 2441*7c478bd9Sstevel@tonic-gate else if (tmi->dec_data.ivec_usage == IVEC_REUSE) 2442*7c478bd9Sstevel@tonic-gate bcopy(tmi->dec_data.ivec, tmi->dec_data.block, 2443*7c478bd9Sstevel@tonic-gate tmi->dec_data.blocklen); 2444*7c478bd9Sstevel@tonic-gate 2445*7c478bd9Sstevel@tonic-gate if (tmi->dec_data.method == CRYPT_METHOD_DES3_CBC_SHA1) { 2446*7c478bd9Sstevel@tonic-gate /* 2447*7c478bd9Sstevel@tonic-gate * Do not decrypt the HMAC at the end 2448*7c478bd9Sstevel@tonic-gate */ 2449*7c478bd9Sstevel@tonic-gate int decrypt_len = inlen - hash->hash_len; 2450*7c478bd9Sstevel@tonic-gate 2451*7c478bd9Sstevel@tonic-gate /* 2452*7c478bd9Sstevel@tonic-gate * Move the wptr so the mblk appears to end 2453*7c478bd9Sstevel@tonic-gate * BEFORE the HMAC section. 2454*7c478bd9Sstevel@tonic-gate */ 2455*7c478bd9Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + decrypt_len; 2456*7c478bd9Sstevel@tonic-gate 2457*7c478bd9Sstevel@tonic-gate /* 2458*7c478bd9Sstevel@tonic-gate * Because we are using KEF, we must manually update our 2459*7c478bd9Sstevel@tonic-gate * IV. 2460*7c478bd9Sstevel@tonic-gate */ 2461*7c478bd9Sstevel@tonic-gate if (tmi->dec_data.ivec_usage == IVEC_ONETIME) { 2462*7c478bd9Sstevel@tonic-gate bcopy(mp->b_rptr + decrypt_len - tmi->dec_data.ivlen, 2463*7c478bd9Sstevel@tonic-gate nextiv, tmi->dec_data.ivlen); 2464*7c478bd9Sstevel@tonic-gate } 2465*7c478bd9Sstevel@tonic-gate 2466*7c478bd9Sstevel@tonic-gate result = kef_decr_hmac(&tmi->dec_data, mp, decrypt_len, 2467*7c478bd9Sstevel@tonic-gate (char *)newcksum, hash->hash_len); 2468*7c478bd9Sstevel@tonic-gate } else { 2469*7c478bd9Sstevel@tonic-gate /* 2470*7c478bd9Sstevel@tonic-gate * Because we are using KEF, we must manually update our 2471*7c478bd9Sstevel@tonic-gate * IV. 2472*7c478bd9Sstevel@tonic-gate */ 2473*7c478bd9Sstevel@tonic-gate if (tmi->dec_data.ivec_usage == IVEC_ONETIME) { 2474*7c478bd9Sstevel@tonic-gate bcopy(mp->b_wptr - tmi->enc_data.ivlen, nextiv, 2475*7c478bd9Sstevel@tonic-gate tmi->dec_data.ivlen); 2476*7c478bd9Sstevel@tonic-gate } 2477*7c478bd9Sstevel@tonic-gate result = kef_crypt(&tmi->dec_data, (void *)mp, 2478*7c478bd9Sstevel@tonic-gate CRYPTO_DATA_MBLK, (size_t)inlen, CRYPT_DECRYPT); 2479*7c478bd9Sstevel@tonic-gate } 2480*7c478bd9Sstevel@tonic-gate if (result != CRYPTO_SUCCESS) { 2481*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 2482*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 2483*7c478bd9Sstevel@tonic-gate "des_cbc_decrypt: kef_crypt decrypt " 2484*7c478bd9Sstevel@tonic-gate "failed - error %0x", result); 2485*7c478bd9Sstevel@tonic-gate #endif 2486*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_ERROR; 2487*7c478bd9Sstevel@tonic-gate mp->b_rptr = mp->b_datap->db_base; 2488*7c478bd9Sstevel@tonic-gate *mp->b_rptr = EIO; 2489*7c478bd9Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + sizeof (char); 2490*7c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 2491*7c478bd9Sstevel@tonic-gate mp->b_cont = NULL; 2492*7c478bd9Sstevel@tonic-gate qreply(WR(q), mp); 2493*7c478bd9Sstevel@tonic-gate return (NULL); 2494*7c478bd9Sstevel@tonic-gate } 2495*7c478bd9Sstevel@tonic-gate 2496*7c478bd9Sstevel@tonic-gate /* 2497*7c478bd9Sstevel@tonic-gate * Manually update the IV, KEF does not track this for us. 2498*7c478bd9Sstevel@tonic-gate */ 2499*7c478bd9Sstevel@tonic-gate if (tmi->dec_data.ivec_usage == IVEC_ONETIME) { 2500*7c478bd9Sstevel@tonic-gate bcopy(nextiv, tmi->dec_data.block, tmi->dec_data.ivlen); 2501*7c478bd9Sstevel@tonic-gate } 2502*7c478bd9Sstevel@tonic-gate 2503*7c478bd9Sstevel@tonic-gate /* Verify the checksum(if necessary) */ 2504*7c478bd9Sstevel@tonic-gate if (hash->hash_len > 0) { 2505*7c478bd9Sstevel@tonic-gate if (tmi->dec_data.method == CRYPT_METHOD_DES3_CBC_SHA1) { 2506*7c478bd9Sstevel@tonic-gate bcopy(mp->b_rptr + inlen - hash->hash_len, cksum, 2507*7c478bd9Sstevel@tonic-gate hash->hash_len); 2508*7c478bd9Sstevel@tonic-gate } else { 2509*7c478bd9Sstevel@tonic-gate bcopy(optr + hash->confound_len, cksum, hash->hash_len); 2510*7c478bd9Sstevel@tonic-gate 2511*7c478bd9Sstevel@tonic-gate /* zero the cksum in the buffer */ 2512*7c478bd9Sstevel@tonic-gate ASSERT(optr + hash->confound_len + hash->hash_len <= 2513*7c478bd9Sstevel@tonic-gate DB_LIM(mp)); 2514*7c478bd9Sstevel@tonic-gate bzero(optr + hash->confound_len, hash->hash_len); 2515*7c478bd9Sstevel@tonic-gate 2516*7c478bd9Sstevel@tonic-gate /* calculate MD5 chksum of confounder + input */ 2517*7c478bd9Sstevel@tonic-gate if (hash->hashfunc) { 2518*7c478bd9Sstevel@tonic-gate (void) hash->hashfunc(newcksum, optr, inlen); 2519*7c478bd9Sstevel@tonic-gate } 2520*7c478bd9Sstevel@tonic-gate } 2521*7c478bd9Sstevel@tonic-gate 2522*7c478bd9Sstevel@tonic-gate if (bcmp(cksum, newcksum, hash->hash_len)) { 2523*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 2524*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "des_cbc_decrypt: checksum " 2525*7c478bd9Sstevel@tonic-gate "verification failed"); 2526*7c478bd9Sstevel@tonic-gate #endif 2527*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_ERROR; 2528*7c478bd9Sstevel@tonic-gate mp->b_rptr = mp->b_datap->db_base; 2529*7c478bd9Sstevel@tonic-gate *mp->b_rptr = EIO; 2530*7c478bd9Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + sizeof (char); 2531*7c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 2532*7c478bd9Sstevel@tonic-gate mp->b_cont = NULL; 2533*7c478bd9Sstevel@tonic-gate qreply(WR(q), mp); 2534*7c478bd9Sstevel@tonic-gate return (NULL); 2535*7c478bd9Sstevel@tonic-gate } 2536*7c478bd9Sstevel@tonic-gate } 2537*7c478bd9Sstevel@tonic-gate 2538*7c478bd9Sstevel@tonic-gate datalen = inlen - hash->confound_len - hash->hash_len; 2539*7c478bd9Sstevel@tonic-gate 2540*7c478bd9Sstevel@tonic-gate /* Move just the decrypted input into place if necessary */ 2541*7c478bd9Sstevel@tonic-gate if (hash->confound_len > 0 || hash->hash_len > 0) { 2542*7c478bd9Sstevel@tonic-gate if (tmi->dec_data.method == CRYPT_METHOD_DES3_CBC_SHA1) 2543*7c478bd9Sstevel@tonic-gate mp->b_rptr += hash->confound_len; 2544*7c478bd9Sstevel@tonic-gate else 2545*7c478bd9Sstevel@tonic-gate mp->b_rptr += hash->confound_len + hash->hash_len; 2546*7c478bd9Sstevel@tonic-gate } 2547*7c478bd9Sstevel@tonic-gate 2548*7c478bd9Sstevel@tonic-gate ASSERT(mp->b_rptr + datalen <= DB_LIM(mp)); 2549*7c478bd9Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + datalen; 2550*7c478bd9Sstevel@tonic-gate 2551*7c478bd9Sstevel@tonic-gate return (mp); 2552*7c478bd9Sstevel@tonic-gate } 2553*7c478bd9Sstevel@tonic-gate 2554*7c478bd9Sstevel@tonic-gate static mblk_t * 2555*7c478bd9Sstevel@tonic-gate do_decrypt(queue_t *q, mblk_t *mp) 2556*7c478bd9Sstevel@tonic-gate { 2557*7c478bd9Sstevel@tonic-gate struct tmodinfo *tmi = (struct tmodinfo *)q->q_ptr; 2558*7c478bd9Sstevel@tonic-gate mblk_t *outmp; 2559*7c478bd9Sstevel@tonic-gate 2560*7c478bd9Sstevel@tonic-gate switch (tmi->dec_data.method) { 2561*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_DES_CFB: 2562*7c478bd9Sstevel@tonic-gate outmp = des_cfb_decrypt(q, tmi, mp); 2563*7c478bd9Sstevel@tonic-gate break; 2564*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_NONE: 2565*7c478bd9Sstevel@tonic-gate outmp = mp; 2566*7c478bd9Sstevel@tonic-gate break; 2567*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_DES_CBC_NULL: 2568*7c478bd9Sstevel@tonic-gate outmp = des_cbc_decrypt(q, tmi, mp, &null_hash); 2569*7c478bd9Sstevel@tonic-gate break; 2570*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_DES_CBC_MD5: 2571*7c478bd9Sstevel@tonic-gate outmp = des_cbc_decrypt(q, tmi, mp, &md5_hash); 2572*7c478bd9Sstevel@tonic-gate break; 2573*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_DES_CBC_CRC: 2574*7c478bd9Sstevel@tonic-gate outmp = des_cbc_decrypt(q, tmi, mp, &crc32_hash); 2575*7c478bd9Sstevel@tonic-gate break; 2576*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_DES3_CBC_SHA1: 2577*7c478bd9Sstevel@tonic-gate outmp = des_cbc_decrypt(q, tmi, mp, &sha1_hash); 2578*7c478bd9Sstevel@tonic-gate break; 2579*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_ARCFOUR_HMAC_MD5: 2580*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_ARCFOUR_HMAC_MD5_EXP: 2581*7c478bd9Sstevel@tonic-gate outmp = arcfour_hmac_md5_decrypt(q, tmi, mp, &md5_hash); 2582*7c478bd9Sstevel@tonic-gate break; 2583*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_AES128: 2584*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_AES256: 2585*7c478bd9Sstevel@tonic-gate outmp = aes_decrypt(q, tmi, mp, &sha1_hash); 2586*7c478bd9Sstevel@tonic-gate break; 2587*7c478bd9Sstevel@tonic-gate } 2588*7c478bd9Sstevel@tonic-gate return (outmp); 2589*7c478bd9Sstevel@tonic-gate } 2590*7c478bd9Sstevel@tonic-gate 2591*7c478bd9Sstevel@tonic-gate /* 2592*7c478bd9Sstevel@tonic-gate * do_encrypt 2593*7c478bd9Sstevel@tonic-gate * 2594*7c478bd9Sstevel@tonic-gate * Generic encryption routine for a single message block. 2595*7c478bd9Sstevel@tonic-gate * The input mblk may be replaced by some encrypt routines 2596*7c478bd9Sstevel@tonic-gate * because they add extra data in some cases that may exceed 2597*7c478bd9Sstevel@tonic-gate * the input mblk_t size limit. 2598*7c478bd9Sstevel@tonic-gate */ 2599*7c478bd9Sstevel@tonic-gate static mblk_t * 2600*7c478bd9Sstevel@tonic-gate do_encrypt(queue_t *q, mblk_t *mp) 2601*7c478bd9Sstevel@tonic-gate { 2602*7c478bd9Sstevel@tonic-gate struct tmodinfo *tmi = (struct tmodinfo *)q->q_ptr; 2603*7c478bd9Sstevel@tonic-gate mblk_t *outmp; 2604*7c478bd9Sstevel@tonic-gate 2605*7c478bd9Sstevel@tonic-gate switch (tmi->enc_data.method) { 2606*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_DES_CFB: 2607*7c478bd9Sstevel@tonic-gate outmp = des_cfb_encrypt(q, tmi, mp); 2608*7c478bd9Sstevel@tonic-gate break; 2609*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_DES_CBC_NULL: 2610*7c478bd9Sstevel@tonic-gate outmp = des_cbc_encrypt(q, tmi, mp, &null_hash); 2611*7c478bd9Sstevel@tonic-gate break; 2612*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_DES_CBC_MD5: 2613*7c478bd9Sstevel@tonic-gate outmp = des_cbc_encrypt(q, tmi, mp, &md5_hash); 2614*7c478bd9Sstevel@tonic-gate break; 2615*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_DES_CBC_CRC: 2616*7c478bd9Sstevel@tonic-gate outmp = des_cbc_encrypt(q, tmi, mp, &crc32_hash); 2617*7c478bd9Sstevel@tonic-gate break; 2618*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_DES3_CBC_SHA1: 2619*7c478bd9Sstevel@tonic-gate outmp = des_cbc_encrypt(q, tmi, mp, &sha1_hash); 2620*7c478bd9Sstevel@tonic-gate break; 2621*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_ARCFOUR_HMAC_MD5: 2622*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_ARCFOUR_HMAC_MD5_EXP: 2623*7c478bd9Sstevel@tonic-gate outmp = arcfour_hmac_md5_encrypt(q, tmi, mp, &md5_hash); 2624*7c478bd9Sstevel@tonic-gate break; 2625*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_AES128: 2626*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_AES256: 2627*7c478bd9Sstevel@tonic-gate outmp = aes_encrypt(q, tmi, mp, &sha1_hash); 2628*7c478bd9Sstevel@tonic-gate break; 2629*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_NONE: 2630*7c478bd9Sstevel@tonic-gate outmp = mp; 2631*7c478bd9Sstevel@tonic-gate break; 2632*7c478bd9Sstevel@tonic-gate } 2633*7c478bd9Sstevel@tonic-gate return (outmp); 2634*7c478bd9Sstevel@tonic-gate } 2635*7c478bd9Sstevel@tonic-gate 2636*7c478bd9Sstevel@tonic-gate /* 2637*7c478bd9Sstevel@tonic-gate * setup_crypto 2638*7c478bd9Sstevel@tonic-gate * 2639*7c478bd9Sstevel@tonic-gate * This takes the data from the CRYPTIOCSETUP ioctl 2640*7c478bd9Sstevel@tonic-gate * and sets up a cipher_data_t structure for either 2641*7c478bd9Sstevel@tonic-gate * encryption or decryption. This is where the 2642*7c478bd9Sstevel@tonic-gate * key and initialization vector data get stored 2643*7c478bd9Sstevel@tonic-gate * prior to beginning any crypto functions. 2644*7c478bd9Sstevel@tonic-gate * 2645*7c478bd9Sstevel@tonic-gate * Special note: 2646*7c478bd9Sstevel@tonic-gate * Some applications(e.g. telnetd) have ability to switch 2647*7c478bd9Sstevel@tonic-gate * crypto on/off periodically. Thus, the application may call 2648*7c478bd9Sstevel@tonic-gate * the CRYPTIOCSETUP ioctl many times for the same stream. 2649*7c478bd9Sstevel@tonic-gate * If the CRYPTIOCSETUP is called with 0 length key or ivec fields 2650*7c478bd9Sstevel@tonic-gate * assume that the key, block, and saveblock fields that are already 2651*7c478bd9Sstevel@tonic-gate * set from a previous CRIOCSETUP call are still valid. This helps avoid 2652*7c478bd9Sstevel@tonic-gate * a rekeying error that could occur if we overwrite these fields 2653*7c478bd9Sstevel@tonic-gate * with each CRYPTIOCSETUP call. 2654*7c478bd9Sstevel@tonic-gate * In short, sometimes, CRYPTIOCSETUP is used to simply toggle on/off 2655*7c478bd9Sstevel@tonic-gate * without resetting the original crypto parameters. 2656*7c478bd9Sstevel@tonic-gate * 2657*7c478bd9Sstevel@tonic-gate */ 2658*7c478bd9Sstevel@tonic-gate static int 2659*7c478bd9Sstevel@tonic-gate setup_crypto(struct cr_info_t *ci, struct cipher_data_t *cd, int encrypt) 2660*7c478bd9Sstevel@tonic-gate { 2661*7c478bd9Sstevel@tonic-gate uint_t newblocklen; 2662*7c478bd9Sstevel@tonic-gate uint32_t enc_usage = 0, dec_usage = 0; 2663*7c478bd9Sstevel@tonic-gate int rv; 2664*7c478bd9Sstevel@tonic-gate 2665*7c478bd9Sstevel@tonic-gate /* 2666*7c478bd9Sstevel@tonic-gate * Initial sanity checks 2667*7c478bd9Sstevel@tonic-gate */ 2668*7c478bd9Sstevel@tonic-gate if (!CR_METHOD_OK(ci->crypto_method)) { 2669*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "Illegal crypto method (%d)", 2670*7c478bd9Sstevel@tonic-gate ci->crypto_method); 2671*7c478bd9Sstevel@tonic-gate return (EINVAL); 2672*7c478bd9Sstevel@tonic-gate } 2673*7c478bd9Sstevel@tonic-gate if (!CR_OPTIONS_OK(ci->option_mask)) { 2674*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "Illegal crypto options (%d)", 2675*7c478bd9Sstevel@tonic-gate ci->option_mask); 2676*7c478bd9Sstevel@tonic-gate return (EINVAL); 2677*7c478bd9Sstevel@tonic-gate } 2678*7c478bd9Sstevel@tonic-gate if (!CR_IVUSAGE_OK(ci->ivec_usage)) { 2679*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "Illegal ivec usage value (%d)", 2680*7c478bd9Sstevel@tonic-gate ci->ivec_usage); 2681*7c478bd9Sstevel@tonic-gate return (EINVAL); 2682*7c478bd9Sstevel@tonic-gate } 2683*7c478bd9Sstevel@tonic-gate 2684*7c478bd9Sstevel@tonic-gate cd->method = ci->crypto_method; 2685*7c478bd9Sstevel@tonic-gate cd->bytes = 0; 2686*7c478bd9Sstevel@tonic-gate 2687*7c478bd9Sstevel@tonic-gate if (ci->keylen > 0) { 2688*7c478bd9Sstevel@tonic-gate if (cd->key != NULL) { 2689*7c478bd9Sstevel@tonic-gate kmem_free(cd->key, cd->keylen); 2690*7c478bd9Sstevel@tonic-gate cd->key = NULL; 2691*7c478bd9Sstevel@tonic-gate cd->keylen = 0; 2692*7c478bd9Sstevel@tonic-gate } 2693*7c478bd9Sstevel@tonic-gate /* 2694*7c478bd9Sstevel@tonic-gate * cd->key holds the copy of the raw key bytes passed in 2695*7c478bd9Sstevel@tonic-gate * from the userland app. 2696*7c478bd9Sstevel@tonic-gate */ 2697*7c478bd9Sstevel@tonic-gate cd->key = (char *)kmem_alloc((size_t)ci->keylen, KM_SLEEP); 2698*7c478bd9Sstevel@tonic-gate 2699*7c478bd9Sstevel@tonic-gate cd->keylen = ci->keylen; 2700*7c478bd9Sstevel@tonic-gate bcopy(ci->key, cd->key, (size_t)ci->keylen); 2701*7c478bd9Sstevel@tonic-gate } 2702*7c478bd9Sstevel@tonic-gate 2703*7c478bd9Sstevel@tonic-gate /* 2704*7c478bd9Sstevel@tonic-gate * Configure the block size based on the type of cipher. 2705*7c478bd9Sstevel@tonic-gate */ 2706*7c478bd9Sstevel@tonic-gate switch (cd->method) { 2707*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_NONE: 2708*7c478bd9Sstevel@tonic-gate newblocklen = 0; 2709*7c478bd9Sstevel@tonic-gate break; 2710*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_DES_CFB: 2711*7c478bd9Sstevel@tonic-gate newblocklen = DEFAULT_DES_BLOCKLEN; 2712*7c478bd9Sstevel@tonic-gate cd->mech_type = crypto_mech2id(SUN_CKM_DES_ECB); 2713*7c478bd9Sstevel@tonic-gate break; 2714*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_DES_CBC_NULL: 2715*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_DES_CBC_MD5: 2716*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_DES_CBC_CRC: 2717*7c478bd9Sstevel@tonic-gate newblocklen = DEFAULT_DES_BLOCKLEN; 2718*7c478bd9Sstevel@tonic-gate cd->mech_type = crypto_mech2id(SUN_CKM_DES_CBC); 2719*7c478bd9Sstevel@tonic-gate break; 2720*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_DES3_CBC_SHA1: 2721*7c478bd9Sstevel@tonic-gate newblocklen = DEFAULT_DES_BLOCKLEN; 2722*7c478bd9Sstevel@tonic-gate cd->mech_type = crypto_mech2id(SUN_CKM_DES3_CBC); 2723*7c478bd9Sstevel@tonic-gate /* 3DES always uses the old usage constant */ 2724*7c478bd9Sstevel@tonic-gate enc_usage = RCMDV1_USAGE; 2725*7c478bd9Sstevel@tonic-gate dec_usage = RCMDV1_USAGE; 2726*7c478bd9Sstevel@tonic-gate break; 2727*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_ARCFOUR_HMAC_MD5: 2728*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_ARCFOUR_HMAC_MD5_EXP: 2729*7c478bd9Sstevel@tonic-gate newblocklen = 0; 2730*7c478bd9Sstevel@tonic-gate cd->mech_type = crypto_mech2id(SUN_CKM_RC4); 2731*7c478bd9Sstevel@tonic-gate break; 2732*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_AES128: 2733*7c478bd9Sstevel@tonic-gate case CRYPT_METHOD_AES256: 2734*7c478bd9Sstevel@tonic-gate newblocklen = DEFAULT_AES_BLOCKLEN; 2735*7c478bd9Sstevel@tonic-gate cd->mech_type = crypto_mech2id(SUN_CKM_AES_ECB); 2736*7c478bd9Sstevel@tonic-gate enc_usage = AES_ENCRYPT_USAGE; 2737*7c478bd9Sstevel@tonic-gate dec_usage = AES_DECRYPT_USAGE; 2738*7c478bd9Sstevel@tonic-gate break; 2739*7c478bd9Sstevel@tonic-gate } 2740*7c478bd9Sstevel@tonic-gate if (cd->mech_type == CRYPTO_MECH_INVALID) { 2741*7c478bd9Sstevel@tonic-gate return (CRYPTO_FAILED); 2742*7c478bd9Sstevel@tonic-gate } 2743*7c478bd9Sstevel@tonic-gate 2744*7c478bd9Sstevel@tonic-gate /* 2745*7c478bd9Sstevel@tonic-gate * If RC4, initialize the master crypto key used by 2746*7c478bd9Sstevel@tonic-gate * the RC4 algorithm to derive the final encrypt and decrypt keys. 2747*7c478bd9Sstevel@tonic-gate */ 2748*7c478bd9Sstevel@tonic-gate if (cd->keylen > 0 && IS_RC4_METHOD(cd->method)) { 2749*7c478bd9Sstevel@tonic-gate /* 2750*7c478bd9Sstevel@tonic-gate * cd->ckey is a kernel crypto key structure used as the 2751*7c478bd9Sstevel@tonic-gate * master key in the RC4-HMAC crypto operations. 2752*7c478bd9Sstevel@tonic-gate */ 2753*7c478bd9Sstevel@tonic-gate if (cd->ckey == NULL) { 2754*7c478bd9Sstevel@tonic-gate cd->ckey = (crypto_key_t *)kmem_zalloc( 2755*7c478bd9Sstevel@tonic-gate sizeof (crypto_key_t), KM_SLEEP); 2756*7c478bd9Sstevel@tonic-gate } 2757*7c478bd9Sstevel@tonic-gate 2758*7c478bd9Sstevel@tonic-gate cd->ckey->ck_format = CRYPTO_KEY_RAW; 2759*7c478bd9Sstevel@tonic-gate cd->ckey->ck_data = cd->key; 2760*7c478bd9Sstevel@tonic-gate 2761*7c478bd9Sstevel@tonic-gate /* key length for EF is measured in bits */ 2762*7c478bd9Sstevel@tonic-gate cd->ckey->ck_length = cd->keylen * 8; 2763*7c478bd9Sstevel@tonic-gate } 2764*7c478bd9Sstevel@tonic-gate 2765*7c478bd9Sstevel@tonic-gate /* 2766*7c478bd9Sstevel@tonic-gate * cd->block and cd->saveblock are used as temporary storage for 2767*7c478bd9Sstevel@tonic-gate * data that must be carried over between encrypt/decrypt operations 2768*7c478bd9Sstevel@tonic-gate * in some of the "feedback" modes. 2769*7c478bd9Sstevel@tonic-gate */ 2770*7c478bd9Sstevel@tonic-gate if (newblocklen != cd->blocklen) { 2771*7c478bd9Sstevel@tonic-gate if (cd->block != NULL) { 2772*7c478bd9Sstevel@tonic-gate kmem_free(cd->block, cd->blocklen); 2773*7c478bd9Sstevel@tonic-gate cd->block = NULL; 2774*7c478bd9Sstevel@tonic-gate } 2775*7c478bd9Sstevel@tonic-gate 2776*7c478bd9Sstevel@tonic-gate if (cd->saveblock != NULL) { 2777*7c478bd9Sstevel@tonic-gate kmem_free(cd->saveblock, cd->blocklen); 2778*7c478bd9Sstevel@tonic-gate cd->saveblock = NULL; 2779*7c478bd9Sstevel@tonic-gate } 2780*7c478bd9Sstevel@tonic-gate 2781*7c478bd9Sstevel@tonic-gate cd->blocklen = newblocklen; 2782*7c478bd9Sstevel@tonic-gate if (cd->blocklen) { 2783*7c478bd9Sstevel@tonic-gate cd->block = (char *)kmem_zalloc((size_t)cd->blocklen, 2784*7c478bd9Sstevel@tonic-gate KM_SLEEP); 2785*7c478bd9Sstevel@tonic-gate } 2786*7c478bd9Sstevel@tonic-gate 2787*7c478bd9Sstevel@tonic-gate if (cd->method == CRYPT_METHOD_DES_CFB) 2788*7c478bd9Sstevel@tonic-gate cd->saveblock = (char *)kmem_zalloc(cd->blocklen, 2789*7c478bd9Sstevel@tonic-gate KM_SLEEP); 2790*7c478bd9Sstevel@tonic-gate else 2791*7c478bd9Sstevel@tonic-gate cd->saveblock = NULL; 2792*7c478bd9Sstevel@tonic-gate } 2793*7c478bd9Sstevel@tonic-gate 2794*7c478bd9Sstevel@tonic-gate if (ci->iveclen != cd->ivlen) { 2795*7c478bd9Sstevel@tonic-gate if (cd->ivec != NULL) { 2796*7c478bd9Sstevel@tonic-gate kmem_free(cd->ivec, cd->ivlen); 2797*7c478bd9Sstevel@tonic-gate cd->ivec = NULL; 2798*7c478bd9Sstevel@tonic-gate } 2799*7c478bd9Sstevel@tonic-gate if (ci->ivec_usage != IVEC_NEVER && ci->iveclen > 0) { 2800*7c478bd9Sstevel@tonic-gate cd->ivec = (char *)kmem_zalloc((size_t)ci->iveclen, 2801*7c478bd9Sstevel@tonic-gate KM_SLEEP); 2802*7c478bd9Sstevel@tonic-gate cd->ivlen = ci->iveclen; 2803*7c478bd9Sstevel@tonic-gate } else { 2804*7c478bd9Sstevel@tonic-gate cd->ivlen = 0; 2805*7c478bd9Sstevel@tonic-gate cd->ivec = NULL; 2806*7c478bd9Sstevel@tonic-gate } 2807*7c478bd9Sstevel@tonic-gate } 2808*7c478bd9Sstevel@tonic-gate cd->option_mask = ci->option_mask; 2809*7c478bd9Sstevel@tonic-gate 2810*7c478bd9Sstevel@tonic-gate /* 2811*7c478bd9Sstevel@tonic-gate * Old protocol requires a static 'usage' value for 2812*7c478bd9Sstevel@tonic-gate * deriving keys. Yuk. 2813*7c478bd9Sstevel@tonic-gate */ 2814*7c478bd9Sstevel@tonic-gate if (cd->option_mask & CRYPTOPT_RCMD_MODE_V1) { 2815*7c478bd9Sstevel@tonic-gate enc_usage = dec_usage = RCMDV1_USAGE; 2816*7c478bd9Sstevel@tonic-gate } 2817*7c478bd9Sstevel@tonic-gate 2818*7c478bd9Sstevel@tonic-gate if (cd->ivlen > cd->blocklen) { 2819*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "setup_crypto: IV longer than block size"); 2820*7c478bd9Sstevel@tonic-gate return (EINVAL); 2821*7c478bd9Sstevel@tonic-gate } 2822*7c478bd9Sstevel@tonic-gate 2823*7c478bd9Sstevel@tonic-gate /* 2824*7c478bd9Sstevel@tonic-gate * If we are using an IVEC "correctly" (i.e. set it once) 2825*7c478bd9Sstevel@tonic-gate * copy it here. 2826*7c478bd9Sstevel@tonic-gate */ 2827*7c478bd9Sstevel@tonic-gate if (ci->ivec_usage == IVEC_ONETIME && cd->block != NULL) 2828*7c478bd9Sstevel@tonic-gate bcopy(ci->ivec, cd->block, (size_t)cd->ivlen); 2829*7c478bd9Sstevel@tonic-gate 2830*7c478bd9Sstevel@tonic-gate cd->ivec_usage = ci->ivec_usage; 2831*7c478bd9Sstevel@tonic-gate if (cd->ivec != NULL) { 2832*7c478bd9Sstevel@tonic-gate /* Save the original IVEC in case we need it later */ 2833*7c478bd9Sstevel@tonic-gate bcopy(ci->ivec, cd->ivec, (size_t)cd->ivlen); 2834*7c478bd9Sstevel@tonic-gate } 2835*7c478bd9Sstevel@tonic-gate /* 2836*7c478bd9Sstevel@tonic-gate * Special handling for 3DES-SHA1-HMAC and AES crypto: 2837*7c478bd9Sstevel@tonic-gate * generate derived keys and context templates 2838*7c478bd9Sstevel@tonic-gate * for better performance. 2839*7c478bd9Sstevel@tonic-gate */ 2840*7c478bd9Sstevel@tonic-gate if (cd->method == CRYPT_METHOD_DES3_CBC_SHA1 || 2841*7c478bd9Sstevel@tonic-gate IS_AES_METHOD(cd->method)) { 2842*7c478bd9Sstevel@tonic-gate crypto_mechanism_t enc_mech; 2843*7c478bd9Sstevel@tonic-gate crypto_mechanism_t hmac_mech; 2844*7c478bd9Sstevel@tonic-gate 2845*7c478bd9Sstevel@tonic-gate if (cd->d_encr_key.ck_data != NULL) { 2846*7c478bd9Sstevel@tonic-gate bzero(cd->d_encr_key.ck_data, cd->keylen); 2847*7c478bd9Sstevel@tonic-gate kmem_free(cd->d_encr_key.ck_data, cd->keylen); 2848*7c478bd9Sstevel@tonic-gate } 2849*7c478bd9Sstevel@tonic-gate 2850*7c478bd9Sstevel@tonic-gate if (cd->d_hmac_key.ck_data != NULL) { 2851*7c478bd9Sstevel@tonic-gate bzero(cd->d_hmac_key.ck_data, cd->keylen); 2852*7c478bd9Sstevel@tonic-gate kmem_free(cd->d_hmac_key.ck_data, cd->keylen); 2853*7c478bd9Sstevel@tonic-gate } 2854*7c478bd9Sstevel@tonic-gate 2855*7c478bd9Sstevel@tonic-gate if (cd->enc_tmpl != NULL) 2856*7c478bd9Sstevel@tonic-gate (void) crypto_destroy_ctx_template(cd->enc_tmpl); 2857*7c478bd9Sstevel@tonic-gate 2858*7c478bd9Sstevel@tonic-gate if (cd->hmac_tmpl != NULL) 2859*7c478bd9Sstevel@tonic-gate (void) crypto_destroy_ctx_template(cd->hmac_tmpl); 2860*7c478bd9Sstevel@tonic-gate 2861*7c478bd9Sstevel@tonic-gate enc_mech.cm_type = cd->mech_type; 2862*7c478bd9Sstevel@tonic-gate enc_mech.cm_param = cd->ivec; 2863*7c478bd9Sstevel@tonic-gate enc_mech.cm_param_len = cd->ivlen; 2864*7c478bd9Sstevel@tonic-gate 2865*7c478bd9Sstevel@tonic-gate hmac_mech.cm_type = sha1_hmac_mech; 2866*7c478bd9Sstevel@tonic-gate hmac_mech.cm_param = NULL; 2867*7c478bd9Sstevel@tonic-gate hmac_mech.cm_param_len = 0; 2868*7c478bd9Sstevel@tonic-gate 2869*7c478bd9Sstevel@tonic-gate /* 2870*7c478bd9Sstevel@tonic-gate * Create the derived keys. 2871*7c478bd9Sstevel@tonic-gate */ 2872*7c478bd9Sstevel@tonic-gate rv = create_derived_keys(cd, 2873*7c478bd9Sstevel@tonic-gate (encrypt ? enc_usage : dec_usage), 2874*7c478bd9Sstevel@tonic-gate &cd->d_encr_key, &cd->d_hmac_key); 2875*7c478bd9Sstevel@tonic-gate 2876*7c478bd9Sstevel@tonic-gate if (rv != CRYPTO_SUCCESS) { 2877*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "failed to create derived " 2878*7c478bd9Sstevel@tonic-gate "keys: %0x", rv); 2879*7c478bd9Sstevel@tonic-gate return (CRYPTO_FAILED); 2880*7c478bd9Sstevel@tonic-gate } 2881*7c478bd9Sstevel@tonic-gate 2882*7c478bd9Sstevel@tonic-gate rv = crypto_create_ctx_template(&enc_mech, 2883*7c478bd9Sstevel@tonic-gate &cd->d_encr_key, 2884*7c478bd9Sstevel@tonic-gate &cd->enc_tmpl, KM_SLEEP); 2885*7c478bd9Sstevel@tonic-gate if (rv == CRYPTO_MECH_NOT_SUPPORTED) { 2886*7c478bd9Sstevel@tonic-gate cd->enc_tmpl = NULL; 2887*7c478bd9Sstevel@tonic-gate } else if (rv != CRYPTO_SUCCESS) { 2888*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "failed to create enc template " 2889*7c478bd9Sstevel@tonic-gate "for d_encr_key: %0x", rv); 2890*7c478bd9Sstevel@tonic-gate return (CRYPTO_FAILED); 2891*7c478bd9Sstevel@tonic-gate } 2892*7c478bd9Sstevel@tonic-gate 2893*7c478bd9Sstevel@tonic-gate rv = crypto_create_ctx_template(&hmac_mech, 2894*7c478bd9Sstevel@tonic-gate &cd->d_hmac_key, 2895*7c478bd9Sstevel@tonic-gate &cd->hmac_tmpl, KM_SLEEP); 2896*7c478bd9Sstevel@tonic-gate if (rv == CRYPTO_MECH_NOT_SUPPORTED) { 2897*7c478bd9Sstevel@tonic-gate cd->hmac_tmpl = NULL; 2898*7c478bd9Sstevel@tonic-gate } else if (rv != CRYPTO_SUCCESS) { 2899*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "failed to create hmac template:" 2900*7c478bd9Sstevel@tonic-gate " %0x", rv); 2901*7c478bd9Sstevel@tonic-gate return (CRYPTO_FAILED); 2902*7c478bd9Sstevel@tonic-gate } 2903*7c478bd9Sstevel@tonic-gate } else if (IS_RC4_METHOD(cd->method)) { 2904*7c478bd9Sstevel@tonic-gate bzero(&cd->d_encr_key, sizeof (crypto_key_t)); 2905*7c478bd9Sstevel@tonic-gate bzero(&cd->d_hmac_key, sizeof (crypto_key_t)); 2906*7c478bd9Sstevel@tonic-gate cd->ctx = NULL; 2907*7c478bd9Sstevel@tonic-gate cd->enc_tmpl = NULL; 2908*7c478bd9Sstevel@tonic-gate cd->hmac_tmpl = NULL; 2909*7c478bd9Sstevel@tonic-gate } 2910*7c478bd9Sstevel@tonic-gate 2911*7c478bd9Sstevel@tonic-gate /* Final sanity checks, make sure no fields are NULL */ 2912*7c478bd9Sstevel@tonic-gate if (cd->method != CRYPT_METHOD_NONE) { 2913*7c478bd9Sstevel@tonic-gate if (cd->block == NULL && cd->blocklen > 0) { 2914*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 2915*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 2916*7c478bd9Sstevel@tonic-gate "setup_crypto: IV block not allocated"); 2917*7c478bd9Sstevel@tonic-gate #endif 2918*7c478bd9Sstevel@tonic-gate return (ENOMEM); 2919*7c478bd9Sstevel@tonic-gate } 2920*7c478bd9Sstevel@tonic-gate if (cd->key == NULL && cd->keylen > 0) { 2921*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 2922*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 2923*7c478bd9Sstevel@tonic-gate "setup_crypto: key block not allocated"); 2924*7c478bd9Sstevel@tonic-gate #endif 2925*7c478bd9Sstevel@tonic-gate return (ENOMEM); 2926*7c478bd9Sstevel@tonic-gate } 2927*7c478bd9Sstevel@tonic-gate if (cd->method == CRYPT_METHOD_DES_CFB && 2928*7c478bd9Sstevel@tonic-gate cd->saveblock == NULL && cd->blocklen > 0) { 2929*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 2930*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 2931*7c478bd9Sstevel@tonic-gate "setup_crypto: save block not allocated"); 2932*7c478bd9Sstevel@tonic-gate #endif 2933*7c478bd9Sstevel@tonic-gate return (ENOMEM); 2934*7c478bd9Sstevel@tonic-gate } 2935*7c478bd9Sstevel@tonic-gate if (cd->ivec == NULL && cd->ivlen > 0) { 2936*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 2937*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 2938*7c478bd9Sstevel@tonic-gate "setup_crypto: IV not allocated"); 2939*7c478bd9Sstevel@tonic-gate #endif 2940*7c478bd9Sstevel@tonic-gate return (ENOMEM); 2941*7c478bd9Sstevel@tonic-gate } 2942*7c478bd9Sstevel@tonic-gate } 2943*7c478bd9Sstevel@tonic-gate return (0); 2944*7c478bd9Sstevel@tonic-gate } 2945*7c478bd9Sstevel@tonic-gate 2946*7c478bd9Sstevel@tonic-gate /* 2947*7c478bd9Sstevel@tonic-gate * RCMDS require a 4 byte, clear text 2948*7c478bd9Sstevel@tonic-gate * length field before each message. 2949*7c478bd9Sstevel@tonic-gate * Add it now. 2950*7c478bd9Sstevel@tonic-gate */ 2951*7c478bd9Sstevel@tonic-gate static mblk_t * 2952*7c478bd9Sstevel@tonic-gate mklenmp(mblk_t *bp, uint32_t len) 2953*7c478bd9Sstevel@tonic-gate { 2954*7c478bd9Sstevel@tonic-gate mblk_t *lenmp; 2955*7c478bd9Sstevel@tonic-gate uchar_t *ucp; 2956*7c478bd9Sstevel@tonic-gate 2957*7c478bd9Sstevel@tonic-gate if (bp->b_rptr - 4 < DB_BASE(bp) || DB_REF(bp) > 1) { 2958*7c478bd9Sstevel@tonic-gate lenmp = allocb(4, BPRI_MED); 2959*7c478bd9Sstevel@tonic-gate if (lenmp != NULL) { 2960*7c478bd9Sstevel@tonic-gate lenmp->b_rptr = lenmp->b_wptr = DB_LIM(lenmp); 2961*7c478bd9Sstevel@tonic-gate linkb(lenmp, bp); 2962*7c478bd9Sstevel@tonic-gate bp = lenmp; 2963*7c478bd9Sstevel@tonic-gate } 2964*7c478bd9Sstevel@tonic-gate } 2965*7c478bd9Sstevel@tonic-gate ucp = bp->b_rptr; 2966*7c478bd9Sstevel@tonic-gate *--ucp = len; 2967*7c478bd9Sstevel@tonic-gate *--ucp = len >> 8; 2968*7c478bd9Sstevel@tonic-gate *--ucp = len >> 16; 2969*7c478bd9Sstevel@tonic-gate *--ucp = len >> 24; 2970*7c478bd9Sstevel@tonic-gate 2971*7c478bd9Sstevel@tonic-gate bp->b_rptr = ucp; 2972*7c478bd9Sstevel@tonic-gate 2973*7c478bd9Sstevel@tonic-gate return (bp); 2974*7c478bd9Sstevel@tonic-gate } 2975*7c478bd9Sstevel@tonic-gate 2976*7c478bd9Sstevel@tonic-gate /* 2977*7c478bd9Sstevel@tonic-gate * encrypt_msgb 2978*7c478bd9Sstevel@tonic-gate * 2979*7c478bd9Sstevel@tonic-gate * encrypt a single message. This routine adds the 2980*7c478bd9Sstevel@tonic-gate * RCMD overhead bytes when necessary. 2981*7c478bd9Sstevel@tonic-gate */ 2982*7c478bd9Sstevel@tonic-gate static mblk_t * 2983*7c478bd9Sstevel@tonic-gate encrypt_msgb(queue_t *q, struct tmodinfo *tmi, mblk_t *mp) 2984*7c478bd9Sstevel@tonic-gate { 2985*7c478bd9Sstevel@tonic-gate mblk_t *newmp; 2986*7c478bd9Sstevel@tonic-gate size_t plainlen; 2987*7c478bd9Sstevel@tonic-gate size_t headspace; 2988*7c478bd9Sstevel@tonic-gate 2989*7c478bd9Sstevel@tonic-gate if (tmi->enc_data.method == CRYPT_METHOD_NONE) { 2990*7c478bd9Sstevel@tonic-gate return (mp); 2991*7c478bd9Sstevel@tonic-gate } 2992*7c478bd9Sstevel@tonic-gate 2993*7c478bd9Sstevel@tonic-gate /* 2994*7c478bd9Sstevel@tonic-gate * process message 2995*7c478bd9Sstevel@tonic-gate */ 2996*7c478bd9Sstevel@tonic-gate newmp = NULL; 2997*7c478bd9Sstevel@tonic-gate if ((plainlen = MBLKL(mp)) > 0) { 2998*7c478bd9Sstevel@tonic-gate mblk_t *cbp; 2999*7c478bd9Sstevel@tonic-gate size_t cipherlen; 3000*7c478bd9Sstevel@tonic-gate size_t extra = 0; 3001*7c478bd9Sstevel@tonic-gate uint32_t ptlen = (uint32_t)plainlen; 3002*7c478bd9Sstevel@tonic-gate 3003*7c478bd9Sstevel@tonic-gate /* 3004*7c478bd9Sstevel@tonic-gate * If we are using the "NEW" RCMD mode, 3005*7c478bd9Sstevel@tonic-gate * add 4 bytes to the plaintext for the 3006*7c478bd9Sstevel@tonic-gate * plaintext length that gets prepended 3007*7c478bd9Sstevel@tonic-gate * before encrypting. 3008*7c478bd9Sstevel@tonic-gate */ 3009*7c478bd9Sstevel@tonic-gate if (tmi->enc_data.option_mask & CRYPTOPT_RCMD_MODE_V2) 3010*7c478bd9Sstevel@tonic-gate ptlen += 4; 3011*7c478bd9Sstevel@tonic-gate 3012*7c478bd9Sstevel@tonic-gate cipherlen = encrypt_size(&tmi->enc_data, (size_t)ptlen); 3013*7c478bd9Sstevel@tonic-gate 3014*7c478bd9Sstevel@tonic-gate /* 3015*7c478bd9Sstevel@tonic-gate * if we must allocb, then make sure its enough 3016*7c478bd9Sstevel@tonic-gate * to hold the length field so we dont have to allocb 3017*7c478bd9Sstevel@tonic-gate * again down below in 'mklenmp' 3018*7c478bd9Sstevel@tonic-gate */ 3019*7c478bd9Sstevel@tonic-gate if (ANY_RCMD_MODE(tmi->enc_data.option_mask)) { 3020*7c478bd9Sstevel@tonic-gate extra = sizeof (uint32_t); 3021*7c478bd9Sstevel@tonic-gate } 3022*7c478bd9Sstevel@tonic-gate 3023*7c478bd9Sstevel@tonic-gate /* 3024*7c478bd9Sstevel@tonic-gate * Calculate how much space is needed in front of 3025*7c478bd9Sstevel@tonic-gate * the data. 3026*7c478bd9Sstevel@tonic-gate */ 3027*7c478bd9Sstevel@tonic-gate headspace = plaintext_offset(&tmi->enc_data); 3028*7c478bd9Sstevel@tonic-gate 3029*7c478bd9Sstevel@tonic-gate /* 3030*7c478bd9Sstevel@tonic-gate * If the current block is too small, reallocate 3031*7c478bd9Sstevel@tonic-gate * one large enough to hold the hdr, tail, and 3032*7c478bd9Sstevel@tonic-gate * ciphertext. 3033*7c478bd9Sstevel@tonic-gate */ 3034*7c478bd9Sstevel@tonic-gate if ((cipherlen + extra >= MBLKSIZE(mp)) || DB_REF(mp) > 1) { 3035*7c478bd9Sstevel@tonic-gate int sz = P2ROUNDUP(cipherlen+extra, 8); 3036*7c478bd9Sstevel@tonic-gate 3037*7c478bd9Sstevel@tonic-gate cbp = allocb_tmpl(sz, mp); 3038*7c478bd9Sstevel@tonic-gate if (cbp == NULL) { 3039*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 3040*7c478bd9Sstevel@tonic-gate "allocb (%d bytes) failed", sz); 3041*7c478bd9Sstevel@tonic-gate return (NULL); 3042*7c478bd9Sstevel@tonic-gate } 3043*7c478bd9Sstevel@tonic-gate 3044*7c478bd9Sstevel@tonic-gate cbp->b_cont = mp->b_cont; 3045*7c478bd9Sstevel@tonic-gate 3046*7c478bd9Sstevel@tonic-gate /* 3047*7c478bd9Sstevel@tonic-gate * headspace includes the length fields needed 3048*7c478bd9Sstevel@tonic-gate * for the RCMD modes (v1 == 4 bytes, V2 = 8) 3049*7c478bd9Sstevel@tonic-gate */ 3050*7c478bd9Sstevel@tonic-gate cbp->b_rptr = DB_BASE(cbp) + headspace; 3051*7c478bd9Sstevel@tonic-gate 3052*7c478bd9Sstevel@tonic-gate ASSERT(cbp->b_rptr + P2ROUNDUP(plainlen, 8) 3053*7c478bd9Sstevel@tonic-gate <= DB_LIM(cbp)); 3054*7c478bd9Sstevel@tonic-gate 3055*7c478bd9Sstevel@tonic-gate bcopy(mp->b_rptr, cbp->b_rptr, plainlen); 3056*7c478bd9Sstevel@tonic-gate cbp->b_wptr = cbp->b_rptr + plainlen; 3057*7c478bd9Sstevel@tonic-gate 3058*7c478bd9Sstevel@tonic-gate freeb(mp); 3059*7c478bd9Sstevel@tonic-gate } else { 3060*7c478bd9Sstevel@tonic-gate size_t extra = 0; 3061*7c478bd9Sstevel@tonic-gate cbp = mp; 3062*7c478bd9Sstevel@tonic-gate 3063*7c478bd9Sstevel@tonic-gate /* 3064*7c478bd9Sstevel@tonic-gate * Some ciphers add HMAC after the final block 3065*7c478bd9Sstevel@tonic-gate * of the ciphertext, not at the beginning like the 3066*7c478bd9Sstevel@tonic-gate * 1-DES ciphers. 3067*7c478bd9Sstevel@tonic-gate */ 3068*7c478bd9Sstevel@tonic-gate if (tmi->enc_data.method == 3069*7c478bd9Sstevel@tonic-gate CRYPT_METHOD_DES3_CBC_SHA1 || 3070*7c478bd9Sstevel@tonic-gate IS_AES_METHOD(tmi->enc_data.method)) { 3071*7c478bd9Sstevel@tonic-gate extra = sha1_hash.hash_len; 3072*7c478bd9Sstevel@tonic-gate } 3073*7c478bd9Sstevel@tonic-gate 3074*7c478bd9Sstevel@tonic-gate /* 3075*7c478bd9Sstevel@tonic-gate * Make sure the rptr is positioned correctly so that 3076*7c478bd9Sstevel@tonic-gate * routines later do not have to shift this data around 3077*7c478bd9Sstevel@tonic-gate */ 3078*7c478bd9Sstevel@tonic-gate if ((cbp->b_rptr + P2ROUNDUP(plainlen + extra, 8) > 3079*7c478bd9Sstevel@tonic-gate DB_LIM(cbp)) || 3080*7c478bd9Sstevel@tonic-gate (cbp->b_rptr - headspace < DB_BASE(cbp))) { 3081*7c478bd9Sstevel@tonic-gate ovbcopy(cbp->b_rptr, DB_BASE(cbp) + headspace, 3082*7c478bd9Sstevel@tonic-gate plainlen); 3083*7c478bd9Sstevel@tonic-gate cbp->b_rptr = DB_BASE(cbp) + headspace; 3084*7c478bd9Sstevel@tonic-gate cbp->b_wptr = cbp->b_rptr + plainlen; 3085*7c478bd9Sstevel@tonic-gate } 3086*7c478bd9Sstevel@tonic-gate } 3087*7c478bd9Sstevel@tonic-gate 3088*7c478bd9Sstevel@tonic-gate ASSERT(cbp->b_rptr - headspace >= DB_BASE(cbp)); 3089*7c478bd9Sstevel@tonic-gate ASSERT(cbp->b_wptr <= DB_LIM(cbp)); 3090*7c478bd9Sstevel@tonic-gate 3091*7c478bd9Sstevel@tonic-gate /* 3092*7c478bd9Sstevel@tonic-gate * If using RCMD_MODE_V2 (new rcmd mode), prepend 3093*7c478bd9Sstevel@tonic-gate * the plaintext length before the actual plaintext. 3094*7c478bd9Sstevel@tonic-gate */ 3095*7c478bd9Sstevel@tonic-gate if (tmi->enc_data.option_mask & CRYPTOPT_RCMD_MODE_V2) { 3096*7c478bd9Sstevel@tonic-gate cbp->b_rptr -= RCMD_LEN_SZ; 3097*7c478bd9Sstevel@tonic-gate 3098*7c478bd9Sstevel@tonic-gate /* put plaintext length at head of buffer */ 3099*7c478bd9Sstevel@tonic-gate *(cbp->b_rptr + 3) = (uchar_t)(plainlen & 0xff); 3100*7c478bd9Sstevel@tonic-gate *(cbp->b_rptr + 2) = (uchar_t)((plainlen >> 8) & 0xff); 3101*7c478bd9Sstevel@tonic-gate *(cbp->b_rptr + 1) = (uchar_t)((plainlen >> 16) & 0xff); 3102*7c478bd9Sstevel@tonic-gate *(cbp->b_rptr) = (uchar_t)((plainlen >> 24) & 0xff); 3103*7c478bd9Sstevel@tonic-gate } 3104*7c478bd9Sstevel@tonic-gate 3105*7c478bd9Sstevel@tonic-gate newmp = do_encrypt(q, cbp); 3106*7c478bd9Sstevel@tonic-gate 3107*7c478bd9Sstevel@tonic-gate if (newmp != NULL && 3108*7c478bd9Sstevel@tonic-gate (tmi->enc_data.option_mask & 3109*7c478bd9Sstevel@tonic-gate (CRYPTOPT_RCMD_MODE_V1 | CRYPTOPT_RCMD_MODE_V2))) { 3110*7c478bd9Sstevel@tonic-gate mblk_t *lp; 3111*7c478bd9Sstevel@tonic-gate /* 3112*7c478bd9Sstevel@tonic-gate * Add length field, required when this is 3113*7c478bd9Sstevel@tonic-gate * used to encrypt "r*" commands(rlogin, rsh) 3114*7c478bd9Sstevel@tonic-gate * with Kerberos. 3115*7c478bd9Sstevel@tonic-gate */ 3116*7c478bd9Sstevel@tonic-gate lp = mklenmp(newmp, plainlen); 3117*7c478bd9Sstevel@tonic-gate 3118*7c478bd9Sstevel@tonic-gate if (lp == NULL) { 3119*7c478bd9Sstevel@tonic-gate freeb(newmp); 3120*7c478bd9Sstevel@tonic-gate return (NULL); 3121*7c478bd9Sstevel@tonic-gate } else { 3122*7c478bd9Sstevel@tonic-gate newmp = lp; 3123*7c478bd9Sstevel@tonic-gate } 3124*7c478bd9Sstevel@tonic-gate } 3125*7c478bd9Sstevel@tonic-gate } else { 3126*7c478bd9Sstevel@tonic-gate freeb(mp); 3127*7c478bd9Sstevel@tonic-gate } 3128*7c478bd9Sstevel@tonic-gate 3129*7c478bd9Sstevel@tonic-gate return (newmp); 3130*7c478bd9Sstevel@tonic-gate } 3131*7c478bd9Sstevel@tonic-gate 3132*7c478bd9Sstevel@tonic-gate /* 3133*7c478bd9Sstevel@tonic-gate * cryptmodwsrv 3134*7c478bd9Sstevel@tonic-gate * 3135*7c478bd9Sstevel@tonic-gate * Service routine for the write queue. 3136*7c478bd9Sstevel@tonic-gate * 3137*7c478bd9Sstevel@tonic-gate * Because data may be placed in the queue to hold between 3138*7c478bd9Sstevel@tonic-gate * the CRYPTIOCSTOP and CRYPTIOCSTART ioctls, the service routine is needed. 3139*7c478bd9Sstevel@tonic-gate */ 3140*7c478bd9Sstevel@tonic-gate static int 3141*7c478bd9Sstevel@tonic-gate cryptmodwsrv(queue_t *q) 3142*7c478bd9Sstevel@tonic-gate { 3143*7c478bd9Sstevel@tonic-gate mblk_t *mp; 3144*7c478bd9Sstevel@tonic-gate struct tmodinfo *tmi = (struct tmodinfo *)q->q_ptr; 3145*7c478bd9Sstevel@tonic-gate 3146*7c478bd9Sstevel@tonic-gate while ((mp = getq(q)) != NULL) { 3147*7c478bd9Sstevel@tonic-gate switch (mp->b_datap->db_type) { 3148*7c478bd9Sstevel@tonic-gate default: 3149*7c478bd9Sstevel@tonic-gate /* 3150*7c478bd9Sstevel@tonic-gate * wput does not queue anything > QPCTL 3151*7c478bd9Sstevel@tonic-gate */ 3152*7c478bd9Sstevel@tonic-gate if (!canputnext(q) || 3153*7c478bd9Sstevel@tonic-gate !(tmi->ready & CRYPT_WRITE_READY)) { 3154*7c478bd9Sstevel@tonic-gate if (!putbq(q, mp)) { 3155*7c478bd9Sstevel@tonic-gate freemsg(mp); 3156*7c478bd9Sstevel@tonic-gate } 3157*7c478bd9Sstevel@tonic-gate return (0); 3158*7c478bd9Sstevel@tonic-gate } 3159*7c478bd9Sstevel@tonic-gate putnext(q, mp); 3160*7c478bd9Sstevel@tonic-gate break; 3161*7c478bd9Sstevel@tonic-gate case M_DATA: 3162*7c478bd9Sstevel@tonic-gate if (canputnext(q) && (tmi->ready & CRYPT_WRITE_READY)) { 3163*7c478bd9Sstevel@tonic-gate mblk_t *bp; 3164*7c478bd9Sstevel@tonic-gate mblk_t *newmsg = NULL; 3165*7c478bd9Sstevel@tonic-gate 3166*7c478bd9Sstevel@tonic-gate /* 3167*7c478bd9Sstevel@tonic-gate * If multiple msgs, concat into 1 3168*7c478bd9Sstevel@tonic-gate * to minimize crypto operations later. 3169*7c478bd9Sstevel@tonic-gate */ 3170*7c478bd9Sstevel@tonic-gate if (mp->b_cont != NULL) { 3171*7c478bd9Sstevel@tonic-gate bp = msgpullup(mp, -1); 3172*7c478bd9Sstevel@tonic-gate if (bp != NULL) { 3173*7c478bd9Sstevel@tonic-gate freemsg(mp); 3174*7c478bd9Sstevel@tonic-gate mp = bp; 3175*7c478bd9Sstevel@tonic-gate } 3176*7c478bd9Sstevel@tonic-gate } 3177*7c478bd9Sstevel@tonic-gate newmsg = encrypt_msgb(q, tmi, mp); 3178*7c478bd9Sstevel@tonic-gate if (newmsg != NULL) 3179*7c478bd9Sstevel@tonic-gate putnext(q, newmsg); 3180*7c478bd9Sstevel@tonic-gate } else { 3181*7c478bd9Sstevel@tonic-gate if (!putbq(q, mp)) { 3182*7c478bd9Sstevel@tonic-gate freemsg(mp); 3183*7c478bd9Sstevel@tonic-gate } 3184*7c478bd9Sstevel@tonic-gate return (0); 3185*7c478bd9Sstevel@tonic-gate } 3186*7c478bd9Sstevel@tonic-gate break; 3187*7c478bd9Sstevel@tonic-gate } 3188*7c478bd9Sstevel@tonic-gate } 3189*7c478bd9Sstevel@tonic-gate return (0); 3190*7c478bd9Sstevel@tonic-gate } 3191*7c478bd9Sstevel@tonic-gate 3192*7c478bd9Sstevel@tonic-gate static void 3193*7c478bd9Sstevel@tonic-gate start_stream(queue_t *wq, mblk_t *mp, uchar_t dir) 3194*7c478bd9Sstevel@tonic-gate { 3195*7c478bd9Sstevel@tonic-gate mblk_t *newmp = NULL; 3196*7c478bd9Sstevel@tonic-gate struct tmodinfo *tmi = (struct tmodinfo *)wq->q_ptr; 3197*7c478bd9Sstevel@tonic-gate 3198*7c478bd9Sstevel@tonic-gate if (dir == CRYPT_ENCRYPT) { 3199*7c478bd9Sstevel@tonic-gate tmi->ready |= CRYPT_WRITE_READY; 3200*7c478bd9Sstevel@tonic-gate (void) (STRLOG(CRYPTMOD_ID, 0, 5, SL_TRACE|SL_NOTE, 3201*7c478bd9Sstevel@tonic-gate "start_stream: restart ENCRYPT/WRITE q")); 3202*7c478bd9Sstevel@tonic-gate 3203*7c478bd9Sstevel@tonic-gate enableok(wq); 3204*7c478bd9Sstevel@tonic-gate qenable(wq); 3205*7c478bd9Sstevel@tonic-gate } else if (dir == CRYPT_DECRYPT) { 3206*7c478bd9Sstevel@tonic-gate /* 3207*7c478bd9Sstevel@tonic-gate * put any extra data in the RD 3208*7c478bd9Sstevel@tonic-gate * queue to be processed and 3209*7c478bd9Sstevel@tonic-gate * sent back up. 3210*7c478bd9Sstevel@tonic-gate */ 3211*7c478bd9Sstevel@tonic-gate newmp = mp->b_cont; 3212*7c478bd9Sstevel@tonic-gate mp->b_cont = NULL; 3213*7c478bd9Sstevel@tonic-gate 3214*7c478bd9Sstevel@tonic-gate tmi->ready |= CRYPT_READ_READY; 3215*7c478bd9Sstevel@tonic-gate (void) (STRLOG(CRYPTMOD_ID, 0, 5, 3216*7c478bd9Sstevel@tonic-gate SL_TRACE|SL_NOTE, 3217*7c478bd9Sstevel@tonic-gate "start_stream: restart " 3218*7c478bd9Sstevel@tonic-gate "DECRYPT/READ q")); 3219*7c478bd9Sstevel@tonic-gate 3220*7c478bd9Sstevel@tonic-gate if (newmp != NULL) 3221*7c478bd9Sstevel@tonic-gate if (!putbq(RD(wq), newmp)) 3222*7c478bd9Sstevel@tonic-gate freemsg(newmp); 3223*7c478bd9Sstevel@tonic-gate 3224*7c478bd9Sstevel@tonic-gate enableok(RD(wq)); 3225*7c478bd9Sstevel@tonic-gate qenable(RD(wq)); 3226*7c478bd9Sstevel@tonic-gate } 3227*7c478bd9Sstevel@tonic-gate 3228*7c478bd9Sstevel@tonic-gate miocack(wq, mp, 0, 0); 3229*7c478bd9Sstevel@tonic-gate } 3230*7c478bd9Sstevel@tonic-gate 3231*7c478bd9Sstevel@tonic-gate /* 3232*7c478bd9Sstevel@tonic-gate * Write-side put procedure. Its main task is to detect ioctls and 3233*7c478bd9Sstevel@tonic-gate * FLUSH operations. Other message types are passed on through. 3234*7c478bd9Sstevel@tonic-gate */ 3235*7c478bd9Sstevel@tonic-gate static void 3236*7c478bd9Sstevel@tonic-gate cryptmodwput(queue_t *wq, mblk_t *mp) 3237*7c478bd9Sstevel@tonic-gate { 3238*7c478bd9Sstevel@tonic-gate struct iocblk *iocp; 3239*7c478bd9Sstevel@tonic-gate struct tmodinfo *tmi = (struct tmodinfo *)wq->q_ptr; 3240*7c478bd9Sstevel@tonic-gate int ret, err; 3241*7c478bd9Sstevel@tonic-gate 3242*7c478bd9Sstevel@tonic-gate switch (mp->b_datap->db_type) { 3243*7c478bd9Sstevel@tonic-gate case M_DATA: 3244*7c478bd9Sstevel@tonic-gate if (wq->q_first == NULL && canputnext(wq) && 3245*7c478bd9Sstevel@tonic-gate (tmi->ready & CRYPT_WRITE_READY) && 3246*7c478bd9Sstevel@tonic-gate tmi->enc_data.method == CRYPT_METHOD_NONE) { 3247*7c478bd9Sstevel@tonic-gate putnext(wq, mp); 3248*7c478bd9Sstevel@tonic-gate return; 3249*7c478bd9Sstevel@tonic-gate } 3250*7c478bd9Sstevel@tonic-gate /* else, put it in the service queue */ 3251*7c478bd9Sstevel@tonic-gate if (!putq(wq, mp)) { 3252*7c478bd9Sstevel@tonic-gate freemsg(mp); 3253*7c478bd9Sstevel@tonic-gate } 3254*7c478bd9Sstevel@tonic-gate break; 3255*7c478bd9Sstevel@tonic-gate case M_FLUSH: 3256*7c478bd9Sstevel@tonic-gate if (*mp->b_rptr & FLUSHW) { 3257*7c478bd9Sstevel@tonic-gate flushq(wq, FLUSHDATA); 3258*7c478bd9Sstevel@tonic-gate } 3259*7c478bd9Sstevel@tonic-gate putnext(wq, mp); 3260*7c478bd9Sstevel@tonic-gate break; 3261*7c478bd9Sstevel@tonic-gate case M_IOCTL: 3262*7c478bd9Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr; 3263*7c478bd9Sstevel@tonic-gate switch (iocp->ioc_cmd) { 3264*7c478bd9Sstevel@tonic-gate case CRYPTIOCSETUP: 3265*7c478bd9Sstevel@tonic-gate ret = 0; 3266*7c478bd9Sstevel@tonic-gate (void) (STRLOG(CRYPTMOD_ID, 0, 5, 3267*7c478bd9Sstevel@tonic-gate SL_TRACE | SL_NOTE, 3268*7c478bd9Sstevel@tonic-gate "wput: got CRYPTIOCSETUP " 3269*7c478bd9Sstevel@tonic-gate "ioctl(%d)", iocp->ioc_cmd)); 3270*7c478bd9Sstevel@tonic-gate 3271*7c478bd9Sstevel@tonic-gate if ((err = miocpullup(mp, 3272*7c478bd9Sstevel@tonic-gate sizeof (struct cr_info_t))) != 0) { 3273*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 3274*7c478bd9Sstevel@tonic-gate "wput: miocpullup failed for cr_info_t"); 3275*7c478bd9Sstevel@tonic-gate miocnak(wq, mp, 0, err); 3276*7c478bd9Sstevel@tonic-gate } else { 3277*7c478bd9Sstevel@tonic-gate struct cr_info_t *ci; 3278*7c478bd9Sstevel@tonic-gate ci = (struct cr_info_t *)mp->b_cont->b_rptr; 3279*7c478bd9Sstevel@tonic-gate 3280*7c478bd9Sstevel@tonic-gate if (ci->direction_mask & CRYPT_ENCRYPT) { 3281*7c478bd9Sstevel@tonic-gate ret = setup_crypto(ci, &tmi->enc_data, 1); 3282*7c478bd9Sstevel@tonic-gate } 3283*7c478bd9Sstevel@tonic-gate 3284*7c478bd9Sstevel@tonic-gate if (ret == 0 && 3285*7c478bd9Sstevel@tonic-gate (ci->direction_mask & CRYPT_DECRYPT)) { 3286*7c478bd9Sstevel@tonic-gate ret = setup_crypto(ci, &tmi->dec_data, 0); 3287*7c478bd9Sstevel@tonic-gate } 3288*7c478bd9Sstevel@tonic-gate if (ret == 0 && 3289*7c478bd9Sstevel@tonic-gate (ci->direction_mask & CRYPT_DECRYPT) && 3290*7c478bd9Sstevel@tonic-gate ANY_RCMD_MODE(tmi->dec_data.option_mask)) { 3291*7c478bd9Sstevel@tonic-gate bzero(&tmi->rcmd_state, 3292*7c478bd9Sstevel@tonic-gate sizeof (tmi->rcmd_state)); 3293*7c478bd9Sstevel@tonic-gate } 3294*7c478bd9Sstevel@tonic-gate if (ret == 0) { 3295*7c478bd9Sstevel@tonic-gate miocack(wq, mp, 0, 0); 3296*7c478bd9Sstevel@tonic-gate } else { 3297*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 3298*7c478bd9Sstevel@tonic-gate "wput: setup_crypto failed"); 3299*7c478bd9Sstevel@tonic-gate miocnak(wq, mp, 0, ret); 3300*7c478bd9Sstevel@tonic-gate } 3301*7c478bd9Sstevel@tonic-gate (void) (STRLOG(CRYPTMOD_ID, 0, 5, 3302*7c478bd9Sstevel@tonic-gate SL_TRACE|SL_NOTE, 3303*7c478bd9Sstevel@tonic-gate "wput: done with SETUP " 3304*7c478bd9Sstevel@tonic-gate "ioctl")); 3305*7c478bd9Sstevel@tonic-gate } 3306*7c478bd9Sstevel@tonic-gate break; 3307*7c478bd9Sstevel@tonic-gate case CRYPTIOCSTOP: 3308*7c478bd9Sstevel@tonic-gate (void) (STRLOG(CRYPTMOD_ID, 0, 5, 3309*7c478bd9Sstevel@tonic-gate SL_TRACE|SL_NOTE, 3310*7c478bd9Sstevel@tonic-gate "wput: got CRYPTIOCSTOP " 3311*7c478bd9Sstevel@tonic-gate "ioctl(%d)", iocp->ioc_cmd)); 3312*7c478bd9Sstevel@tonic-gate 3313*7c478bd9Sstevel@tonic-gate if ((err = miocpullup(mp, sizeof (uint32_t))) != 0) { 3314*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 3315*7c478bd9Sstevel@tonic-gate "wput: CRYPTIOCSTOP ioctl wrong " 3316*7c478bd9Sstevel@tonic-gate "size (%d should be %d)", 3317*7c478bd9Sstevel@tonic-gate (int)iocp->ioc_count, 3318*7c478bd9Sstevel@tonic-gate (int)sizeof (uint32_t)); 3319*7c478bd9Sstevel@tonic-gate miocnak(wq, mp, 0, err); 3320*7c478bd9Sstevel@tonic-gate } else { 3321*7c478bd9Sstevel@tonic-gate uint32_t *stopdir; 3322*7c478bd9Sstevel@tonic-gate 3323*7c478bd9Sstevel@tonic-gate stopdir = (uint32_t *)mp->b_cont->b_rptr; 3324*7c478bd9Sstevel@tonic-gate if (!CR_DIRECTION_OK(*stopdir)) { 3325*7c478bd9Sstevel@tonic-gate miocnak(wq, mp, 0, EINVAL); 3326*7c478bd9Sstevel@tonic-gate return; 3327*7c478bd9Sstevel@tonic-gate } 3328*7c478bd9Sstevel@tonic-gate 3329*7c478bd9Sstevel@tonic-gate /* disable the queues until further notice */ 3330*7c478bd9Sstevel@tonic-gate if (*stopdir & CRYPT_ENCRYPT) { 3331*7c478bd9Sstevel@tonic-gate noenable(wq); 3332*7c478bd9Sstevel@tonic-gate tmi->ready &= ~CRYPT_WRITE_READY; 3333*7c478bd9Sstevel@tonic-gate } 3334*7c478bd9Sstevel@tonic-gate if (*stopdir & CRYPT_DECRYPT) { 3335*7c478bd9Sstevel@tonic-gate noenable(RD(wq)); 3336*7c478bd9Sstevel@tonic-gate tmi->ready &= ~CRYPT_READ_READY; 3337*7c478bd9Sstevel@tonic-gate } 3338*7c478bd9Sstevel@tonic-gate 3339*7c478bd9Sstevel@tonic-gate miocack(wq, mp, 0, 0); 3340*7c478bd9Sstevel@tonic-gate } 3341*7c478bd9Sstevel@tonic-gate break; 3342*7c478bd9Sstevel@tonic-gate case CRYPTIOCSTARTDEC: 3343*7c478bd9Sstevel@tonic-gate (void) (STRLOG(CRYPTMOD_ID, 0, 5, 3344*7c478bd9Sstevel@tonic-gate SL_TRACE|SL_NOTE, 3345*7c478bd9Sstevel@tonic-gate "wput: got CRYPTIOCSTARTDEC " 3346*7c478bd9Sstevel@tonic-gate "ioctl(%d)", iocp->ioc_cmd)); 3347*7c478bd9Sstevel@tonic-gate 3348*7c478bd9Sstevel@tonic-gate start_stream(wq, mp, CRYPT_DECRYPT); 3349*7c478bd9Sstevel@tonic-gate break; 3350*7c478bd9Sstevel@tonic-gate case CRYPTIOCSTARTENC: 3351*7c478bd9Sstevel@tonic-gate (void) (STRLOG(CRYPTMOD_ID, 0, 5, 3352*7c478bd9Sstevel@tonic-gate SL_TRACE|SL_NOTE, 3353*7c478bd9Sstevel@tonic-gate "wput: got CRYPTIOCSTARTENC " 3354*7c478bd9Sstevel@tonic-gate "ioctl(%d)", iocp->ioc_cmd)); 3355*7c478bd9Sstevel@tonic-gate 3356*7c478bd9Sstevel@tonic-gate start_stream(wq, mp, CRYPT_ENCRYPT); 3357*7c478bd9Sstevel@tonic-gate break; 3358*7c478bd9Sstevel@tonic-gate default: 3359*7c478bd9Sstevel@tonic-gate putnext(wq, mp); 3360*7c478bd9Sstevel@tonic-gate break; 3361*7c478bd9Sstevel@tonic-gate } 3362*7c478bd9Sstevel@tonic-gate break; 3363*7c478bd9Sstevel@tonic-gate default: 3364*7c478bd9Sstevel@tonic-gate if (queclass(mp) < QPCTL) { 3365*7c478bd9Sstevel@tonic-gate if (wq->q_first != NULL || !canputnext(wq)) { 3366*7c478bd9Sstevel@tonic-gate if (!putq(wq, mp)) 3367*7c478bd9Sstevel@tonic-gate freemsg(mp); 3368*7c478bd9Sstevel@tonic-gate return; 3369*7c478bd9Sstevel@tonic-gate } 3370*7c478bd9Sstevel@tonic-gate } 3371*7c478bd9Sstevel@tonic-gate putnext(wq, mp); 3372*7c478bd9Sstevel@tonic-gate break; 3373*7c478bd9Sstevel@tonic-gate } 3374*7c478bd9Sstevel@tonic-gate } 3375*7c478bd9Sstevel@tonic-gate 3376*7c478bd9Sstevel@tonic-gate /* 3377*7c478bd9Sstevel@tonic-gate * decrypt_rcmd_mblks 3378*7c478bd9Sstevel@tonic-gate * 3379*7c478bd9Sstevel@tonic-gate * Because kerberized r* commands(rsh, rlogin, etc) 3380*7c478bd9Sstevel@tonic-gate * use a 4 byte length field to indicate the # of 3381*7c478bd9Sstevel@tonic-gate * PLAINTEXT bytes that are encrypted in the field 3382*7c478bd9Sstevel@tonic-gate * that follows, we must parse out each message and 3383*7c478bd9Sstevel@tonic-gate * break out the length fields prior to sending them 3384*7c478bd9Sstevel@tonic-gate * upstream to our Solaris r* clients/servers which do 3385*7c478bd9Sstevel@tonic-gate * NOT understand this format. 3386*7c478bd9Sstevel@tonic-gate * 3387*7c478bd9Sstevel@tonic-gate * Kerberized/encrypted message format: 3388*7c478bd9Sstevel@tonic-gate * ------------------------------- 3389*7c478bd9Sstevel@tonic-gate * | XXXX | N bytes of ciphertext| 3390*7c478bd9Sstevel@tonic-gate * ------------------------------- 3391*7c478bd9Sstevel@tonic-gate * 3392*7c478bd9Sstevel@tonic-gate * Where: XXXX = number of plaintext bytes that were encrypted in 3393*7c478bd9Sstevel@tonic-gate * to make the ciphertext field. This is done 3394*7c478bd9Sstevel@tonic-gate * because we are using a cipher that pads out to 3395*7c478bd9Sstevel@tonic-gate * an 8 byte boundary. We only want the application 3396*7c478bd9Sstevel@tonic-gate * layer to see the correct number of plain text bytes, 3397*7c478bd9Sstevel@tonic-gate * not plaintext + pad. So, after we decrypt, we 3398*7c478bd9Sstevel@tonic-gate * must trim the output block down to the intended 3399*7c478bd9Sstevel@tonic-gate * plaintext length and eliminate the pad bytes. 3400*7c478bd9Sstevel@tonic-gate * 3401*7c478bd9Sstevel@tonic-gate * This routine takes the entire input message, breaks it into 3402*7c478bd9Sstevel@tonic-gate * a new message that does not contain these length fields and 3403*7c478bd9Sstevel@tonic-gate * returns a message consisting of mblks filled with just ciphertext. 3404*7c478bd9Sstevel@tonic-gate * 3405*7c478bd9Sstevel@tonic-gate */ 3406*7c478bd9Sstevel@tonic-gate static mblk_t * 3407*7c478bd9Sstevel@tonic-gate decrypt_rcmd_mblks(queue_t *q, mblk_t *mp) 3408*7c478bd9Sstevel@tonic-gate { 3409*7c478bd9Sstevel@tonic-gate mblk_t *newmp = NULL; 3410*7c478bd9Sstevel@tonic-gate size_t msglen; 3411*7c478bd9Sstevel@tonic-gate struct tmodinfo *tmi = (struct tmodinfo *)q->q_ptr; 3412*7c478bd9Sstevel@tonic-gate 3413*7c478bd9Sstevel@tonic-gate msglen = msgsize(mp); 3414*7c478bd9Sstevel@tonic-gate 3415*7c478bd9Sstevel@tonic-gate /* 3416*7c478bd9Sstevel@tonic-gate * If we need the length field, get it here. 3417*7c478bd9Sstevel@tonic-gate * Test the "plaintext length" indicator. 3418*7c478bd9Sstevel@tonic-gate */ 3419*7c478bd9Sstevel@tonic-gate if (tmi->rcmd_state.pt_len == 0) { 3420*7c478bd9Sstevel@tonic-gate uint32_t elen; 3421*7c478bd9Sstevel@tonic-gate int tocopy; 3422*7c478bd9Sstevel@tonic-gate mblk_t *nextp; 3423*7c478bd9Sstevel@tonic-gate 3424*7c478bd9Sstevel@tonic-gate /* 3425*7c478bd9Sstevel@tonic-gate * Make sure we have recieved all 4 bytes of the 3426*7c478bd9Sstevel@tonic-gate * length field. 3427*7c478bd9Sstevel@tonic-gate */ 3428*7c478bd9Sstevel@tonic-gate while (mp != NULL) { 3429*7c478bd9Sstevel@tonic-gate ASSERT(tmi->rcmd_state.cd_len < sizeof (uint32_t)); 3430*7c478bd9Sstevel@tonic-gate 3431*7c478bd9Sstevel@tonic-gate tocopy = sizeof (uint32_t) - 3432*7c478bd9Sstevel@tonic-gate tmi->rcmd_state.cd_len; 3433*7c478bd9Sstevel@tonic-gate if (tocopy > msglen) 3434*7c478bd9Sstevel@tonic-gate tocopy = msglen; 3435*7c478bd9Sstevel@tonic-gate 3436*7c478bd9Sstevel@tonic-gate ASSERT(mp->b_rptr + tocopy <= DB_LIM(mp)); 3437*7c478bd9Sstevel@tonic-gate bcopy(mp->b_rptr, 3438*7c478bd9Sstevel@tonic-gate (char *)(&tmi->rcmd_state.next_len + 3439*7c478bd9Sstevel@tonic-gate tmi->rcmd_state.cd_len), tocopy); 3440*7c478bd9Sstevel@tonic-gate 3441*7c478bd9Sstevel@tonic-gate tmi->rcmd_state.cd_len += tocopy; 3442*7c478bd9Sstevel@tonic-gate 3443*7c478bd9Sstevel@tonic-gate if (tmi->rcmd_state.cd_len >= sizeof (uint32_t)) { 3444*7c478bd9Sstevel@tonic-gate tmi->rcmd_state.next_len = 3445*7c478bd9Sstevel@tonic-gate ntohl(tmi->rcmd_state.next_len); 3446*7c478bd9Sstevel@tonic-gate break; 3447*7c478bd9Sstevel@tonic-gate } 3448*7c478bd9Sstevel@tonic-gate 3449*7c478bd9Sstevel@tonic-gate nextp = mp->b_cont; 3450*7c478bd9Sstevel@tonic-gate mp->b_cont = NULL; 3451*7c478bd9Sstevel@tonic-gate freeb(mp); 3452*7c478bd9Sstevel@tonic-gate mp = nextp; 3453*7c478bd9Sstevel@tonic-gate } 3454*7c478bd9Sstevel@tonic-gate 3455*7c478bd9Sstevel@tonic-gate if (mp == NULL) { 3456*7c478bd9Sstevel@tonic-gate return (NULL); 3457*7c478bd9Sstevel@tonic-gate } 3458*7c478bd9Sstevel@tonic-gate /* 3459*7c478bd9Sstevel@tonic-gate * recalculate the msglen now that we've read the 3460*7c478bd9Sstevel@tonic-gate * length and adjusted the bufptr (b_rptr). 3461*7c478bd9Sstevel@tonic-gate */ 3462*7c478bd9Sstevel@tonic-gate msglen -= tocopy; 3463*7c478bd9Sstevel@tonic-gate mp->b_rptr += tocopy; 3464*7c478bd9Sstevel@tonic-gate 3465*7c478bd9Sstevel@tonic-gate tmi->rcmd_state.pt_len = tmi->rcmd_state.next_len; 3466*7c478bd9Sstevel@tonic-gate 3467*7c478bd9Sstevel@tonic-gate if (tmi->rcmd_state.pt_len <= 0) { 3468*7c478bd9Sstevel@tonic-gate /* 3469*7c478bd9Sstevel@tonic-gate * Return an IO error to break the connection. there 3470*7c478bd9Sstevel@tonic-gate * is no way to recover from this. Usually it means 3471*7c478bd9Sstevel@tonic-gate * the app has incorrectly requested decryption on 3472*7c478bd9Sstevel@tonic-gate * a non-encrypted stream, thus the "pt_len" field 3473*7c478bd9Sstevel@tonic-gate * is negative. 3474*7c478bd9Sstevel@tonic-gate */ 3475*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_ERROR; 3476*7c478bd9Sstevel@tonic-gate mp->b_rptr = mp->b_datap->db_base; 3477*7c478bd9Sstevel@tonic-gate *mp->b_rptr = EIO; 3478*7c478bd9Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + sizeof (char); 3479*7c478bd9Sstevel@tonic-gate 3480*7c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 3481*7c478bd9Sstevel@tonic-gate mp->b_cont = NULL; 3482*7c478bd9Sstevel@tonic-gate qreply(WR(q), mp); 3483*7c478bd9Sstevel@tonic-gate tmi->rcmd_state.cd_len = tmi->rcmd_state.pt_len = 0; 3484*7c478bd9Sstevel@tonic-gate return (NULL); 3485*7c478bd9Sstevel@tonic-gate } 3486*7c478bd9Sstevel@tonic-gate 3487*7c478bd9Sstevel@tonic-gate /* 3488*7c478bd9Sstevel@tonic-gate * If this is V2 mode, then the encrypted data is actually 3489*7c478bd9Sstevel@tonic-gate * 4 bytes bigger than the indicated len because the plaintext 3490*7c478bd9Sstevel@tonic-gate * length is encrypted for an additional security check, but 3491*7c478bd9Sstevel@tonic-gate * its not counted as part of the overall length we just read. 3492*7c478bd9Sstevel@tonic-gate * Strange and confusing, but true. 3493*7c478bd9Sstevel@tonic-gate */ 3494*7c478bd9Sstevel@tonic-gate 3495*7c478bd9Sstevel@tonic-gate if (tmi->dec_data.option_mask & CRYPTOPT_RCMD_MODE_V2) 3496*7c478bd9Sstevel@tonic-gate elen = tmi->rcmd_state.pt_len + 4; 3497*7c478bd9Sstevel@tonic-gate else 3498*7c478bd9Sstevel@tonic-gate elen = tmi->rcmd_state.pt_len; 3499*7c478bd9Sstevel@tonic-gate 3500*7c478bd9Sstevel@tonic-gate tmi->rcmd_state.cd_len = encrypt_size(&tmi->dec_data, elen); 3501*7c478bd9Sstevel@tonic-gate 3502*7c478bd9Sstevel@tonic-gate /* 3503*7c478bd9Sstevel@tonic-gate * Allocate an mblk to hold the cipher text until it is 3504*7c478bd9Sstevel@tonic-gate * all ready to be processed. 3505*7c478bd9Sstevel@tonic-gate */ 3506*7c478bd9Sstevel@tonic-gate tmi->rcmd_state.c_msg = allocb(tmi->rcmd_state.cd_len, 3507*7c478bd9Sstevel@tonic-gate BPRI_HI); 3508*7c478bd9Sstevel@tonic-gate if (tmi->rcmd_state.c_msg == NULL) { 3509*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 3510*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "decrypt_rcmd_msgb: allocb failed " 3511*7c478bd9Sstevel@tonic-gate "for %d bytes", 3512*7c478bd9Sstevel@tonic-gate (int)tmi->rcmd_state.cd_len); 3513*7c478bd9Sstevel@tonic-gate #endif 3514*7c478bd9Sstevel@tonic-gate /* 3515*7c478bd9Sstevel@tonic-gate * Return an IO error to break the connection. 3516*7c478bd9Sstevel@tonic-gate */ 3517*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_ERROR; 3518*7c478bd9Sstevel@tonic-gate mp->b_rptr = mp->b_datap->db_base; 3519*7c478bd9Sstevel@tonic-gate *mp->b_rptr = EIO; 3520*7c478bd9Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + sizeof (char); 3521*7c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 3522*7c478bd9Sstevel@tonic-gate mp->b_cont = NULL; 3523*7c478bd9Sstevel@tonic-gate tmi->rcmd_state.cd_len = tmi->rcmd_state.pt_len = 0; 3524*7c478bd9Sstevel@tonic-gate qreply(WR(q), mp); 3525*7c478bd9Sstevel@tonic-gate return (NULL); 3526*7c478bd9Sstevel@tonic-gate } 3527*7c478bd9Sstevel@tonic-gate } 3528*7c478bd9Sstevel@tonic-gate 3529*7c478bd9Sstevel@tonic-gate /* 3530*7c478bd9Sstevel@tonic-gate * If this entire message was just the length field, 3531*7c478bd9Sstevel@tonic-gate * free and return. The actual data will probably be next. 3532*7c478bd9Sstevel@tonic-gate */ 3533*7c478bd9Sstevel@tonic-gate if (msglen == 0) { 3534*7c478bd9Sstevel@tonic-gate freemsg(mp); 3535*7c478bd9Sstevel@tonic-gate return (NULL); 3536*7c478bd9Sstevel@tonic-gate } 3537*7c478bd9Sstevel@tonic-gate 3538*7c478bd9Sstevel@tonic-gate /* 3539*7c478bd9Sstevel@tonic-gate * Copy as much of the cipher text as possible into 3540*7c478bd9Sstevel@tonic-gate * the new msgb (c_msg). 3541*7c478bd9Sstevel@tonic-gate * 3542*7c478bd9Sstevel@tonic-gate * Logic: if we got some bytes (msglen) and we still 3543*7c478bd9Sstevel@tonic-gate * "need" some bytes (len-rcvd), get them here. 3544*7c478bd9Sstevel@tonic-gate */ 3545*7c478bd9Sstevel@tonic-gate ASSERT(tmi->rcmd_state.c_msg != NULL); 3546*7c478bd9Sstevel@tonic-gate if (msglen > 0 && 3547*7c478bd9Sstevel@tonic-gate (tmi->rcmd_state.cd_len > MBLKL(tmi->rcmd_state.c_msg))) { 3548*7c478bd9Sstevel@tonic-gate mblk_t *bp, *nextp; 3549*7c478bd9Sstevel@tonic-gate size_t n; 3550*7c478bd9Sstevel@tonic-gate 3551*7c478bd9Sstevel@tonic-gate /* 3552*7c478bd9Sstevel@tonic-gate * Walk the mblks and copy just as many bytes as we need 3553*7c478bd9Sstevel@tonic-gate * for this particular block of cipher text. 3554*7c478bd9Sstevel@tonic-gate */ 3555*7c478bd9Sstevel@tonic-gate bp = mp; 3556*7c478bd9Sstevel@tonic-gate while (bp != NULL) { 3557*7c478bd9Sstevel@tonic-gate size_t needed; 3558*7c478bd9Sstevel@tonic-gate size_t tocopy; 3559*7c478bd9Sstevel@tonic-gate n = MBLKL(bp); 3560*7c478bd9Sstevel@tonic-gate 3561*7c478bd9Sstevel@tonic-gate needed = tmi->rcmd_state.cd_len - 3562*7c478bd9Sstevel@tonic-gate MBLKL(tmi->rcmd_state.c_msg); 3563*7c478bd9Sstevel@tonic-gate 3564*7c478bd9Sstevel@tonic-gate tocopy = (needed >= n ? n : needed); 3565*7c478bd9Sstevel@tonic-gate 3566*7c478bd9Sstevel@tonic-gate ASSERT(bp->b_rptr + tocopy <= DB_LIM(bp)); 3567*7c478bd9Sstevel@tonic-gate ASSERT(tmi->rcmd_state.c_msg->b_wptr + tocopy <= 3568*7c478bd9Sstevel@tonic-gate DB_LIM(tmi->rcmd_state.c_msg)); 3569*7c478bd9Sstevel@tonic-gate 3570*7c478bd9Sstevel@tonic-gate /* Copy to end of new mblk */ 3571*7c478bd9Sstevel@tonic-gate bcopy(bp->b_rptr, tmi->rcmd_state.c_msg->b_wptr, 3572*7c478bd9Sstevel@tonic-gate tocopy); 3573*7c478bd9Sstevel@tonic-gate 3574*7c478bd9Sstevel@tonic-gate tmi->rcmd_state.c_msg->b_wptr += tocopy; 3575*7c478bd9Sstevel@tonic-gate 3576*7c478bd9Sstevel@tonic-gate bp->b_rptr += tocopy; 3577*7c478bd9Sstevel@tonic-gate 3578*7c478bd9Sstevel@tonic-gate nextp = bp->b_cont; 3579*7c478bd9Sstevel@tonic-gate 3580*7c478bd9Sstevel@tonic-gate /* 3581*7c478bd9Sstevel@tonic-gate * If we used this whole block, free it and 3582*7c478bd9Sstevel@tonic-gate * move on. 3583*7c478bd9Sstevel@tonic-gate */ 3584*7c478bd9Sstevel@tonic-gate if (!MBLKL(bp)) { 3585*7c478bd9Sstevel@tonic-gate freeb(bp); 3586*7c478bd9Sstevel@tonic-gate bp = NULL; 3587*7c478bd9Sstevel@tonic-gate } 3588*7c478bd9Sstevel@tonic-gate 3589*7c478bd9Sstevel@tonic-gate /* If we got what we needed, stop the loop */ 3590*7c478bd9Sstevel@tonic-gate if (MBLKL(tmi->rcmd_state.c_msg) == 3591*7c478bd9Sstevel@tonic-gate tmi->rcmd_state.cd_len) { 3592*7c478bd9Sstevel@tonic-gate /* 3593*7c478bd9Sstevel@tonic-gate * If there is more data in the message, 3594*7c478bd9Sstevel@tonic-gate * its for another block of cipher text, 3595*7c478bd9Sstevel@tonic-gate * put it back in the queue for next time. 3596*7c478bd9Sstevel@tonic-gate */ 3597*7c478bd9Sstevel@tonic-gate if (bp) { 3598*7c478bd9Sstevel@tonic-gate if (!putbq(q, bp)) 3599*7c478bd9Sstevel@tonic-gate freemsg(bp); 3600*7c478bd9Sstevel@tonic-gate } else if (nextp != NULL) { 3601*7c478bd9Sstevel@tonic-gate /* 3602*7c478bd9Sstevel@tonic-gate * If there is more, put it back in the 3603*7c478bd9Sstevel@tonic-gate * queue for another pass thru. 3604*7c478bd9Sstevel@tonic-gate */ 3605*7c478bd9Sstevel@tonic-gate if (!putbq(q, nextp)) 3606*7c478bd9Sstevel@tonic-gate freemsg(nextp); 3607*7c478bd9Sstevel@tonic-gate } 3608*7c478bd9Sstevel@tonic-gate break; 3609*7c478bd9Sstevel@tonic-gate } 3610*7c478bd9Sstevel@tonic-gate bp = nextp; 3611*7c478bd9Sstevel@tonic-gate } 3612*7c478bd9Sstevel@tonic-gate } 3613*7c478bd9Sstevel@tonic-gate /* 3614*7c478bd9Sstevel@tonic-gate * Finally, if we received all the cipher text data for 3615*7c478bd9Sstevel@tonic-gate * this message, decrypt it into a new msg and send it up 3616*7c478bd9Sstevel@tonic-gate * to the app. 3617*7c478bd9Sstevel@tonic-gate */ 3618*7c478bd9Sstevel@tonic-gate if (tmi->rcmd_state.pt_len > 0 && 3619*7c478bd9Sstevel@tonic-gate MBLKL(tmi->rcmd_state.c_msg) == tmi->rcmd_state.cd_len) { 3620*7c478bd9Sstevel@tonic-gate mblk_t *bp; 3621*7c478bd9Sstevel@tonic-gate mblk_t *newbp; 3622*7c478bd9Sstevel@tonic-gate 3623*7c478bd9Sstevel@tonic-gate /* 3624*7c478bd9Sstevel@tonic-gate * Now we can use our msg that we created when the 3625*7c478bd9Sstevel@tonic-gate * initial message boundary was detected. 3626*7c478bd9Sstevel@tonic-gate */ 3627*7c478bd9Sstevel@tonic-gate bp = tmi->rcmd_state.c_msg; 3628*7c478bd9Sstevel@tonic-gate tmi->rcmd_state.c_msg = NULL; 3629*7c478bd9Sstevel@tonic-gate 3630*7c478bd9Sstevel@tonic-gate newbp = do_decrypt(q, bp); 3631*7c478bd9Sstevel@tonic-gate if (newbp != NULL) { 3632*7c478bd9Sstevel@tonic-gate bp = newbp; 3633*7c478bd9Sstevel@tonic-gate /* 3634*7c478bd9Sstevel@tonic-gate * If using RCMD_MODE_V2 ("new" mode), 3635*7c478bd9Sstevel@tonic-gate * look at the 4 byte plaintext length that 3636*7c478bd9Sstevel@tonic-gate * was just decrypted and compare with the 3637*7c478bd9Sstevel@tonic-gate * original pt_len value that was received. 3638*7c478bd9Sstevel@tonic-gate */ 3639*7c478bd9Sstevel@tonic-gate if (tmi->dec_data.option_mask & 3640*7c478bd9Sstevel@tonic-gate CRYPTOPT_RCMD_MODE_V2) { 3641*7c478bd9Sstevel@tonic-gate uint32_t pt_len2; 3642*7c478bd9Sstevel@tonic-gate 3643*7c478bd9Sstevel@tonic-gate pt_len2 = *(uint32_t *)bp->b_rptr; 3644*7c478bd9Sstevel@tonic-gate pt_len2 = ntohl(pt_len2); 3645*7c478bd9Sstevel@tonic-gate /* 3646*7c478bd9Sstevel@tonic-gate * Make sure the 2 pt len fields agree. 3647*7c478bd9Sstevel@tonic-gate */ 3648*7c478bd9Sstevel@tonic-gate if (pt_len2 != tmi->rcmd_state.pt_len) { 3649*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 3650*7c478bd9Sstevel@tonic-gate "Inconsistent length fields" 3651*7c478bd9Sstevel@tonic-gate " received %d != %d", 3652*7c478bd9Sstevel@tonic-gate (int)tmi->rcmd_state.pt_len, 3653*7c478bd9Sstevel@tonic-gate (int)pt_len2); 3654*7c478bd9Sstevel@tonic-gate bp->b_datap->db_type = M_ERROR; 3655*7c478bd9Sstevel@tonic-gate bp->b_rptr = bp->b_datap->db_base; 3656*7c478bd9Sstevel@tonic-gate *bp->b_rptr = EIO; 3657*7c478bd9Sstevel@tonic-gate bp->b_wptr = bp->b_rptr + sizeof (char); 3658*7c478bd9Sstevel@tonic-gate freemsg(bp->b_cont); 3659*7c478bd9Sstevel@tonic-gate bp->b_cont = NULL; 3660*7c478bd9Sstevel@tonic-gate tmi->rcmd_state.cd_len = 0; 3661*7c478bd9Sstevel@tonic-gate qreply(WR(q), bp); 3662*7c478bd9Sstevel@tonic-gate return (NULL); 3663*7c478bd9Sstevel@tonic-gate } 3664*7c478bd9Sstevel@tonic-gate bp->b_rptr += sizeof (uint32_t); 3665*7c478bd9Sstevel@tonic-gate } 3666*7c478bd9Sstevel@tonic-gate 3667*7c478bd9Sstevel@tonic-gate /* 3668*7c478bd9Sstevel@tonic-gate * Trim the decrypted block the length originally 3669*7c478bd9Sstevel@tonic-gate * indicated by the sender. This is to remove any 3670*7c478bd9Sstevel@tonic-gate * padding bytes that the sender added to satisfy 3671*7c478bd9Sstevel@tonic-gate * requirements of the crypto algorithm. 3672*7c478bd9Sstevel@tonic-gate */ 3673*7c478bd9Sstevel@tonic-gate bp->b_wptr = bp->b_rptr + tmi->rcmd_state.pt_len; 3674*7c478bd9Sstevel@tonic-gate 3675*7c478bd9Sstevel@tonic-gate newmp = bp; 3676*7c478bd9Sstevel@tonic-gate 3677*7c478bd9Sstevel@tonic-gate /* 3678*7c478bd9Sstevel@tonic-gate * Reset our state to indicate we are ready 3679*7c478bd9Sstevel@tonic-gate * for a new message. 3680*7c478bd9Sstevel@tonic-gate */ 3681*7c478bd9Sstevel@tonic-gate tmi->rcmd_state.pt_len = 0; 3682*7c478bd9Sstevel@tonic-gate tmi->rcmd_state.cd_len = 0; 3683*7c478bd9Sstevel@tonic-gate } else { 3684*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 3685*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 3686*7c478bd9Sstevel@tonic-gate "decrypt_rcmd: do_decrypt on %d bytes failed", 3687*7c478bd9Sstevel@tonic-gate (int)tmi->rcmd_state.cd_len); 3688*7c478bd9Sstevel@tonic-gate #endif 3689*7c478bd9Sstevel@tonic-gate /* 3690*7c478bd9Sstevel@tonic-gate * do_decrypt already handled failures, just 3691*7c478bd9Sstevel@tonic-gate * return NULL. 3692*7c478bd9Sstevel@tonic-gate */ 3693*7c478bd9Sstevel@tonic-gate tmi->rcmd_state.pt_len = 0; 3694*7c478bd9Sstevel@tonic-gate tmi->rcmd_state.cd_len = 0; 3695*7c478bd9Sstevel@tonic-gate return (NULL); 3696*7c478bd9Sstevel@tonic-gate } 3697*7c478bd9Sstevel@tonic-gate } 3698*7c478bd9Sstevel@tonic-gate 3699*7c478bd9Sstevel@tonic-gate /* 3700*7c478bd9Sstevel@tonic-gate * return the new message with the 'length' fields removed 3701*7c478bd9Sstevel@tonic-gate */ 3702*7c478bd9Sstevel@tonic-gate return (newmp); 3703*7c478bd9Sstevel@tonic-gate } 3704*7c478bd9Sstevel@tonic-gate 3705*7c478bd9Sstevel@tonic-gate /* 3706*7c478bd9Sstevel@tonic-gate * cryptmodrsrv 3707*7c478bd9Sstevel@tonic-gate * 3708*7c478bd9Sstevel@tonic-gate * Read queue service routine 3709*7c478bd9Sstevel@tonic-gate * Necessary because if the ready flag is not set 3710*7c478bd9Sstevel@tonic-gate * (via CRYPTIOCSTOP/CRYPTIOCSTART ioctls) then the data 3711*7c478bd9Sstevel@tonic-gate * must remain on queue and not be passed along. 3712*7c478bd9Sstevel@tonic-gate */ 3713*7c478bd9Sstevel@tonic-gate static int 3714*7c478bd9Sstevel@tonic-gate cryptmodrsrv(queue_t *q) 3715*7c478bd9Sstevel@tonic-gate { 3716*7c478bd9Sstevel@tonic-gate mblk_t *mp, *bp; 3717*7c478bd9Sstevel@tonic-gate struct tmodinfo *tmi = (struct tmodinfo *)q->q_ptr; 3718*7c478bd9Sstevel@tonic-gate 3719*7c478bd9Sstevel@tonic-gate while ((mp = getq(q)) != NULL) { 3720*7c478bd9Sstevel@tonic-gate switch (mp->b_datap->db_type) { 3721*7c478bd9Sstevel@tonic-gate case M_DATA: 3722*7c478bd9Sstevel@tonic-gate if (canputnext(q) && tmi->ready & CRYPT_READ_READY) { 3723*7c478bd9Sstevel@tonic-gate /* 3724*7c478bd9Sstevel@tonic-gate * Process "rcmd" messages differently because 3725*7c478bd9Sstevel@tonic-gate * they contain a 4 byte plaintext length 3726*7c478bd9Sstevel@tonic-gate * id that needs to be removed. 3727*7c478bd9Sstevel@tonic-gate */ 3728*7c478bd9Sstevel@tonic-gate if (tmi->dec_data.method != CRYPT_METHOD_NONE && 3729*7c478bd9Sstevel@tonic-gate (tmi->dec_data.option_mask & 3730*7c478bd9Sstevel@tonic-gate (CRYPTOPT_RCMD_MODE_V1 | 3731*7c478bd9Sstevel@tonic-gate CRYPTOPT_RCMD_MODE_V2))) { 3732*7c478bd9Sstevel@tonic-gate mp = decrypt_rcmd_mblks(q, mp); 3733*7c478bd9Sstevel@tonic-gate if (mp) 3734*7c478bd9Sstevel@tonic-gate putnext(q, mp); 3735*7c478bd9Sstevel@tonic-gate continue; 3736*7c478bd9Sstevel@tonic-gate } 3737*7c478bd9Sstevel@tonic-gate if ((bp = msgpullup(mp, -1)) != NULL) { 3738*7c478bd9Sstevel@tonic-gate freemsg(mp); 3739*7c478bd9Sstevel@tonic-gate if (MBLKL(bp) > 0) { 3740*7c478bd9Sstevel@tonic-gate mp = do_decrypt(q, bp); 3741*7c478bd9Sstevel@tonic-gate if (mp != NULL) 3742*7c478bd9Sstevel@tonic-gate putnext(q, mp); 3743*7c478bd9Sstevel@tonic-gate } 3744*7c478bd9Sstevel@tonic-gate } 3745*7c478bd9Sstevel@tonic-gate } else { 3746*7c478bd9Sstevel@tonic-gate if (!putbq(q, mp)) { 3747*7c478bd9Sstevel@tonic-gate freemsg(mp); 3748*7c478bd9Sstevel@tonic-gate } 3749*7c478bd9Sstevel@tonic-gate return (0); 3750*7c478bd9Sstevel@tonic-gate } 3751*7c478bd9Sstevel@tonic-gate break; 3752*7c478bd9Sstevel@tonic-gate default: 3753*7c478bd9Sstevel@tonic-gate /* 3754*7c478bd9Sstevel@tonic-gate * rput does not queue anything > QPCTL, so we don't 3755*7c478bd9Sstevel@tonic-gate * need to check for it here. 3756*7c478bd9Sstevel@tonic-gate */ 3757*7c478bd9Sstevel@tonic-gate if (!canputnext(q)) { 3758*7c478bd9Sstevel@tonic-gate if (!putbq(q, mp)) 3759*7c478bd9Sstevel@tonic-gate freemsg(mp); 3760*7c478bd9Sstevel@tonic-gate return (0); 3761*7c478bd9Sstevel@tonic-gate } 3762*7c478bd9Sstevel@tonic-gate putnext(q, mp); 3763*7c478bd9Sstevel@tonic-gate break; 3764*7c478bd9Sstevel@tonic-gate } 3765*7c478bd9Sstevel@tonic-gate } 3766*7c478bd9Sstevel@tonic-gate return (0); 3767*7c478bd9Sstevel@tonic-gate } 3768*7c478bd9Sstevel@tonic-gate 3769*7c478bd9Sstevel@tonic-gate 3770*7c478bd9Sstevel@tonic-gate /* 3771*7c478bd9Sstevel@tonic-gate * Read-side put procedure. 3772*7c478bd9Sstevel@tonic-gate */ 3773*7c478bd9Sstevel@tonic-gate static void 3774*7c478bd9Sstevel@tonic-gate cryptmodrput(queue_t *rq, mblk_t *mp) 3775*7c478bd9Sstevel@tonic-gate { 3776*7c478bd9Sstevel@tonic-gate switch (mp->b_datap->db_type) { 3777*7c478bd9Sstevel@tonic-gate case M_DATA: 3778*7c478bd9Sstevel@tonic-gate if (!putq(rq, mp)) { 3779*7c478bd9Sstevel@tonic-gate freemsg(mp); 3780*7c478bd9Sstevel@tonic-gate } 3781*7c478bd9Sstevel@tonic-gate break; 3782*7c478bd9Sstevel@tonic-gate case M_FLUSH: 3783*7c478bd9Sstevel@tonic-gate if (*mp->b_rptr & FLUSHR) { 3784*7c478bd9Sstevel@tonic-gate flushq(rq, FLUSHALL); 3785*7c478bd9Sstevel@tonic-gate } 3786*7c478bd9Sstevel@tonic-gate putnext(rq, mp); 3787*7c478bd9Sstevel@tonic-gate break; 3788*7c478bd9Sstevel@tonic-gate default: 3789*7c478bd9Sstevel@tonic-gate if (queclass(mp) < QPCTL) { 3790*7c478bd9Sstevel@tonic-gate if (rq->q_first != NULL || !canputnext(rq)) { 3791*7c478bd9Sstevel@tonic-gate if (!putq(rq, mp)) 3792*7c478bd9Sstevel@tonic-gate freemsg(mp); 3793*7c478bd9Sstevel@tonic-gate return; 3794*7c478bd9Sstevel@tonic-gate } 3795*7c478bd9Sstevel@tonic-gate } 3796*7c478bd9Sstevel@tonic-gate putnext(rq, mp); 3797*7c478bd9Sstevel@tonic-gate break; 3798*7c478bd9Sstevel@tonic-gate } 3799*7c478bd9Sstevel@tonic-gate } 3800