Home | History | Annotate | Download | only in io
      1 /*
      2  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
      3  * Use is subject to license terms.
      4  *
      5  * STREAMS Crypto Module
      6  *
      7  * This module is used to facilitate Kerberos encryption
      8  * operations for the telnet daemon and rlogin daemon.
      9  * Because the Solaris telnet and rlogin daemons run mostly
     10  * in-kernel via 'telmod' and 'rlmod', this module must be
     11  * pushed on the STREAM *below* telmod or rlmod.
     12  *
     13  * Parts of the 3DES key derivation code are covered by the
     14  * following copyright.
     15  *
     16  * Copyright (C) 1998 by the FundsXpress, INC.
     17  *
     18  * All rights reserved.
     19  *
     20  * Export of this software from the United States of America may require
     21  * a specific license from the United States Government.  It is the
     22  * responsibility of any person or organization contemplating export to
     23  * obtain such a license before exporting.
     24  *
     25  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
     26  * distribute this software and its documentation for any purpose and
     27  * without fee is hereby granted, provided that the above copyright
     28  * notice appear in all copies and that both that copyright notice and
     29  * this permission notice appear in supporting documentation, and that
     30  * the name of FundsXpress. not be used in advertising or publicity pertaining
     31  * to distribution of the software without specific, written prior
     32  * permission.  FundsXpress makes no representations about the suitability of
     33  * this software for any purpose.  It is provided "as is" without express
     34  * or implied warranty.
     35  *
     36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
     37  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
     38  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
     39  */
     40 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     41 
     42 #include <sys/types.h>
     43 #include <sys/sysmacros.h>
     44 #include <sys/errno.h>
     45 #include <sys/debug.h>
     46 #include <sys/time.h>
     47 #include <sys/stropts.h>
     48 #include <sys/stream.h>
     49 #include <sys/strsubr.h>
     50 #include <sys/strlog.h>
     51 #include <sys/cmn_err.h>
     52 #include <sys/conf.h>
     53 #include <sys/sunddi.h>
     54 #include <sys/kmem.h>
     55 #include <sys/strsun.h>
     56 #include <sys/random.h>
     57 #include <sys/types.h>
     58 #include <sys/byteorder.h>
     59 #include <sys/cryptmod.h>
     60 #include <sys/crc32.h>
     61 #include <sys/policy.h>
     62 
     63 #include <sys/crypto/api.h>
     64 
     65 #include <sys/strft.h>
     66 /*
     67  * Function prototypes.
     68  */
     69 static	int	cryptmodopen(queue_t *, dev_t *, int, int, cred_t *);
     70 static  void	cryptmodrput(queue_t *, mblk_t *);
     71 static  void	cryptmodwput(queue_t *, mblk_t *);
     72 static	int	cryptmodclose(queue_t *);
     73 static	int	cryptmodwsrv(queue_t *);
     74 static	int	cryptmodrsrv(queue_t *);
     75 
     76 static mblk_t *do_encrypt(queue_t *q, mblk_t *mp);
     77 static mblk_t *do_decrypt(queue_t *q, mblk_t *mp);
     78 
     79 #define	CRYPTMOD_ID 5150
     80 
     81 #define	CFB_BLKSZ 8
     82 
     83 #define	K5CLENGTH 5
     84 
     85 static struct module_info	cryptmod_minfo = {
     86 	CRYPTMOD_ID,	/* mi_idnum */
     87 	"cryptmod",	/* mi_idname */
     88 	0,		/* mi_minpsz */
     89 	INFPSZ,		/* mi_maxpsz */
     90 	65536,		/* mi_hiwat */
     91 	1024		/* mi_lowat */
     92 };
     93 
     94 static struct qinit	cryptmod_rinit = {
     95 	(int (*)())cryptmodrput,	/* qi_putp */
     96 	cryptmodrsrv,	/* qi_svc */
     97 	cryptmodopen,	/* qi_qopen */
     98 	cryptmodclose,	/* qi_qclose */
     99 	NULL,		/* qi_qadmin */
    100 	&cryptmod_minfo,	/* qi_minfo */
    101 	NULL		/* qi_mstat */
    102 };
    103 
    104 static struct qinit	cryptmod_winit = {
    105 	(int (*)())cryptmodwput,	/* qi_putp */
    106 	cryptmodwsrv,	/* qi_srvp */
    107 	NULL,		/* qi_qopen */
    108 	NULL,		/* qi_qclose */
    109 	NULL,		/* qi_qadmin */
    110 	&cryptmod_minfo,	/* qi_minfo */
    111 	NULL		/* qi_mstat */
    112 };
    113 
    114 static struct streamtab	cryptmod_info = {
    115 	&cryptmod_rinit,	/* st_rdinit */
    116 	&cryptmod_winit,	/* st_wrinit */
    117 	NULL,	/* st_muxrinit */
    118 	NULL	/* st_muxwinit */
    119 };
    120 
    121 typedef struct {
    122 	uint_t hash_len;
    123 	uint_t confound_len;
    124 	int (*hashfunc)();
    125 } hash_info_t;
    126 
    127 #define	MAX_CKSUM_LEN 20
    128 #define	CONFOUNDER_LEN 8
    129 
    130 #define	SHA1_HASHSIZE 20
    131 #define	MD5_HASHSIZE 16
    132 #define	CRC32_HASHSIZE 4
    133 #define	MSGBUF_SIZE 4096
    134 #define	CONFOUNDER_BYTES 128
    135 
    136 
    137 static int crc32_calc(uchar_t *, uchar_t *, uint_t);
    138 static int md5_calc(uchar_t *, uchar_t *, uint_t);
    139 static int sha1_calc(uchar_t *, uchar_t *, uint_t);
    140 
    141 static hash_info_t null_hash = {0, 0, NULL};
    142 static hash_info_t crc32_hash = {CRC32_HASHSIZE, CONFOUNDER_LEN, crc32_calc};
    143 static hash_info_t md5_hash = {MD5_HASHSIZE, CONFOUNDER_LEN, md5_calc};
    144 static hash_info_t sha1_hash = {SHA1_HASHSIZE, CONFOUNDER_LEN, sha1_calc};
    145 
    146 static crypto_mech_type_t sha1_hmac_mech = CRYPTO_MECH_INVALID;
    147 static crypto_mech_type_t md5_hmac_mech = CRYPTO_MECH_INVALID;
    148 static crypto_mech_type_t sha1_hash_mech = CRYPTO_MECH_INVALID;
    149 static crypto_mech_type_t md5_hash_mech = CRYPTO_MECH_INVALID;
    150 
    151 static int kef_crypt(struct cipher_data_t *, void *,
    152 		    crypto_data_format_t, size_t, int);
    153 static mblk_t *
    154 arcfour_hmac_md5_encrypt(queue_t *, struct tmodinfo *,
    155 		mblk_t *, hash_info_t *);
    156 static mblk_t *
    157 arcfour_hmac_md5_decrypt(queue_t *, struct tmodinfo *,
    158 		mblk_t *, hash_info_t *);
    159 
    160 static int
    161 do_hmac(crypto_mech_type_t, crypto_key_t *, char *, int, char *, int);
    162 
    163 /*
    164  * This is the loadable module wrapper.
    165  */
    166 #include <sys/modctl.h>
    167 
    168 static struct fmodsw fsw = {
    169 	"cryptmod",
    170 	&cryptmod_info,
    171 	D_MP | D_MTQPAIR
    172 };
    173 
    174 /*
    175  * Module linkage information for the kernel.
    176  */
    177 static struct modlstrmod modlstrmod = {
    178 	&mod_strmodops,
    179 	"STREAMS encryption module",
    180 	&fsw
    181 };
    182 
    183 static struct modlinkage modlinkage = {
    184 	MODREV_1,
    185 	&modlstrmod,
    186 	NULL
    187 };
    188 
    189 int
    190 _init(void)
    191 {
    192 	return (mod_install(&modlinkage));
    193 }
    194 
    195 int
    196 _fini(void)
    197 {
    198 	return (mod_remove(&modlinkage));
    199 }
    200 
    201 int
    202 _info(struct modinfo *modinfop)
    203 {
    204 	return (mod_info(&modlinkage, modinfop));
    205 }
    206 
    207 static void
    208 cleanup(struct cipher_data_t *cd)
    209 {
    210 	if (cd->key != NULL) {
    211 		bzero(cd->key, cd->keylen);
    212 		kmem_free(cd->key, cd->keylen);
    213 		cd->key = NULL;
    214 	}
    215 
    216 	if (cd->ckey != NULL) {
    217 		/*
    218 		 * ckey is a crypto_key_t structure which references
    219 		 * "cd->key" for its raw key data.  Since that was already
    220 		 * cleared out, we don't need another "bzero" here.
    221 		 */
    222 		kmem_free(cd->ckey, sizeof (crypto_key_t));
    223 		cd->ckey = NULL;
    224 	}
    225 
    226 	if (cd->block != NULL) {
    227 		kmem_free(cd->block, cd->blocklen);
    228 		cd->block = NULL;
    229 	}
    230 
    231 	if (cd->saveblock != NULL) {
    232 		kmem_free(cd->saveblock, cd->blocklen);
    233 		cd->saveblock = NULL;
    234 	}
    235 
    236 	if (cd->ivec != NULL) {
    237 		kmem_free(cd->ivec, cd->ivlen);
    238 		cd->ivec = NULL;
    239 	}
    240 
    241 	if (cd->d_encr_key.ck_data != NULL) {
    242 		bzero(cd->d_encr_key.ck_data, cd->keylen);
    243 		kmem_free(cd->d_encr_key.ck_data, cd->keylen);
    244 	}
    245 
    246 	if (cd->d_hmac_key.ck_data != NULL) {
    247 		bzero(cd->d_hmac_key.ck_data, cd->keylen);
    248 		kmem_free(cd->d_hmac_key.ck_data, cd->keylen);
    249 	}
    250 
    251 	if (cd->enc_tmpl != NULL)
    252 		(void) crypto_destroy_ctx_template(cd->enc_tmpl);
    253 
    254 	if (cd->hmac_tmpl != NULL)
    255 		(void) crypto_destroy_ctx_template(cd->hmac_tmpl);
    256 
    257 	if (cd->ctx != NULL) {
    258 		crypto_cancel_ctx(cd->ctx);
    259 		cd->ctx = NULL;
    260 	}
    261 }
    262 
    263 /* ARGSUSED */
    264 static int
    265 cryptmodopen(queue_t *rq, dev_t *dev, int oflag, int sflag, cred_t *crp)
    266 {
    267 	struct tmodinfo	*tmi;
    268 	ASSERT(rq);
    269 
    270 	if (sflag != MODOPEN)
    271 		return (EINVAL);
    272 
    273 	(void) (STRLOG(CRYPTMOD_ID, 0, 5, SL_TRACE|SL_NOTE,
    274 			"cryptmodopen: opening module(PID %d)",
    275 			ddi_get_pid()));
    276 
    277 	if (rq->q_ptr != NULL) {
    278 		cmn_err(CE_WARN, "cryptmodopen: already opened");
    279 		return (0);
    280 	}
    281 
    282 	/*
    283 	 * Allocate and initialize per-Stream structure.
    284 	 */
    285 	tmi = (struct tmodinfo *)kmem_zalloc(sizeof (struct tmodinfo),
    286 						KM_SLEEP);
    287 
    288 	tmi->enc_data.method = CRYPT_METHOD_NONE;
    289 	tmi->dec_data.method = CRYPT_METHOD_NONE;
    290 
    291 	tmi->ready = (CRYPT_READ_READY | CRYPT_WRITE_READY);
    292 
    293 	rq->q_ptr = WR(rq)->q_ptr = tmi;
    294 
    295 	sha1_hmac_mech = crypto_mech2id(SUN_CKM_SHA1_HMAC);
    296 	md5_hmac_mech = crypto_mech2id(SUN_CKM_MD5_HMAC);
    297 	sha1_hash_mech = crypto_mech2id(SUN_CKM_SHA1);
    298 	md5_hash_mech = crypto_mech2id(SUN_CKM_MD5);
    299 
    300 	qprocson(rq);
    301 
    302 	return (0);
    303 }
    304 
    305 static int
    306 cryptmodclose(queue_t *rq)
    307 {
    308 	struct tmodinfo *tmi = (struct tmodinfo *)rq->q_ptr;
    309 	ASSERT(tmi);
    310 
    311 	qprocsoff(rq);
    312 
    313 	cleanup(&tmi->enc_data);
    314 	cleanup(&tmi->dec_data);
    315 
    316 	kmem_free(tmi, sizeof (struct tmodinfo));
    317 	rq->q_ptr = WR(rq)->q_ptr = NULL;
    318 
    319 	return (0);
    320 }
    321 
    322 /*
    323  * plaintext_offset
    324  *
    325  * Calculate exactly how much space is needed in front
    326  * of the "plaintext" in an mbuf so it can be positioned
    327  * 1 time instead of potentially moving the data multiple
    328  * times.
    329  */
    330 static int
    331 plaintext_offset(struct cipher_data_t *cd)
    332 {
    333 	int headspace = 0;
    334 
    335 	/* 4 byte length prepended to all RCMD msgs */
    336 	if (ANY_RCMD_MODE(cd->option_mask))
    337 		headspace += RCMD_LEN_SZ;
    338 
    339 	/* RCMD V2 mode adds an additional 4 byte plaintext length */
    340 	if (cd->option_mask & CRYPTOPT_RCMD_MODE_V2)
    341 		headspace += RCMD_LEN_SZ;
    342 
    343 	/* Need extra space for hash and counfounder */
    344 	switch (cd->method) {
    345 	case CRYPT_METHOD_DES_CBC_NULL:
    346 		headspace += null_hash.hash_len + null_hash.confound_len;
    347 		break;
    348 	case CRYPT_METHOD_DES_CBC_CRC:
    349 		headspace += crc32_hash.hash_len + crc32_hash.confound_len;
    350 		break;
    351 	case CRYPT_METHOD_DES_CBC_MD5:
    352 		headspace += md5_hash.hash_len + md5_hash.confound_len;
    353 		break;
    354 	case CRYPT_METHOD_DES3_CBC_SHA1:
    355 		headspace += sha1_hash.confound_len;
    356 		break;
    357 	case CRYPT_METHOD_ARCFOUR_HMAC_MD5:
    358 		headspace += md5_hash.hash_len + md5_hash.confound_len;
    359 		break;
    360 	case CRYPT_METHOD_AES128:
    361 	case CRYPT_METHOD_AES256:
    362 		headspace += DEFAULT_AES_BLOCKLEN;
    363 		break;
    364 	case CRYPT_METHOD_DES_CFB:
    365 	case CRYPT_METHOD_NONE:
    366 		break;
    367 	}
    368 
    369 	return (headspace);
    370 }
    371 /*
    372  * encrypt_size
    373  *
    374  * Calculate the resulting size when encrypting 'plainlen' bytes
    375  * of data.
    376  */
    377 static size_t
    378 encrypt_size(struct cipher_data_t *cd, size_t plainlen)
    379 {
    380 	size_t cipherlen;
    381 
    382 	switch (cd->method) {
    383 	case CRYPT_METHOD_DES_CBC_NULL:
    384 		cipherlen = (size_t)P2ROUNDUP(null_hash.hash_len +
    385 					    plainlen, 8);
    386 		break;
    387 	case CRYPT_METHOD_DES_CBC_MD5:
    388 		cipherlen = (size_t)P2ROUNDUP(md5_hash.hash_len +
    389 					    md5_hash.confound_len +
    390 					    plainlen, 8);
    391 		break;
    392 	case CRYPT_METHOD_DES_CBC_CRC:
    393 		cipherlen = (size_t)P2ROUNDUP(crc32_hash.hash_len +
    394 					    crc32_hash.confound_len +
    395 					    plainlen, 8);
    396 		break;
    397 	case CRYPT_METHOD_DES3_CBC_SHA1:
    398 		cipherlen = (size_t)P2ROUNDUP(sha1_hash.confound_len +
    399 					    plainlen, 8) +
    400 					    sha1_hash.hash_len;
    401 		break;
    402 	case CRYPT_METHOD_ARCFOUR_HMAC_MD5:
    403 		cipherlen = (size_t)P2ROUNDUP(md5_hash.confound_len +
    404 				plainlen, 1) + md5_hash.hash_len;
    405 		break;
    406 	case CRYPT_METHOD_AES128:
    407 	case CRYPT_METHOD_AES256:
    408 		/* No roundup for AES-CBC-CTS */
    409 		cipherlen = DEFAULT_AES_BLOCKLEN + plainlen +
    410 			AES_TRUNCATED_HMAC_LEN;
    411 		break;
    412 	case CRYPT_METHOD_DES_CFB:
    413 	case CRYPT_METHOD_NONE:
    414 		cipherlen = plainlen;
    415 		break;
    416 	}
    417 
    418 	return (cipherlen);
    419 }
    420 
    421 /*
    422  * des_cfb_encrypt
    423  *
    424  * Encrypt the mblk data using DES with cipher feedback.
    425  *
    426  * Given that V[i] is the initial 64 bit vector, V[n] is the nth 64 bit
    427  * vector, D[n] is the nth chunk of 64 bits of data to encrypt
    428  * (decrypt), and O[n] is the nth chunk of 64 bits of encrypted
    429  * (decrypted) data, then:
    430  *
    431  *  V[0] = DES(V[i], key)
    432  *  O[n] = D[n] <exclusive or > V[n]
    433  *  V[n+1] = DES(O[n], key)
    434  *
    435  * The size of the message being encrypted does not change in this
    436  * algorithm, num_bytes in == num_bytes out.
    437  */
    438 static mblk_t *
    439 des_cfb_encrypt(queue_t *q, struct tmodinfo *tmi, mblk_t *mp)
    440 {
    441 	int savedbytes;
    442 	char *iptr, *optr, *lastoutput;
    443 
    444 	lastoutput = optr = (char *)mp->b_rptr;
    445 	iptr = (char *)mp->b_rptr;
    446 	savedbytes = tmi->enc_data.bytes % CFB_BLKSZ;
    447 
    448 	while (iptr < (char *)mp->b_wptr) {
    449 		/*
    450 		 * Do DES-ECB.
    451 		 * The first time this runs, the 'tmi->enc_data.block' will
    452 		 * contain the initialization vector that should have been
    453 		 * passed in with the SETUP ioctl.
    454 		 *
    455 		 * V[n] = DES(V[n-1], key)
    456 		 */
    457 		if (!(tmi->enc_data.bytes % CFB_BLKSZ)) {
    458 			int retval = 0;
    459 			retval = kef_crypt(&tmi->enc_data,
    460 					tmi->enc_data.block,
    461 					CRYPTO_DATA_RAW,
    462 					tmi->enc_data.blocklen,
    463 					CRYPT_ENCRYPT);
    464 
    465 			if (retval != CRYPTO_SUCCESS) {
    466 #ifdef DEBUG
    467 				cmn_err(CE_WARN, "des_cfb_encrypt: kef_crypt "
    468 					"failed - error 0x%0x", retval);
    469 #endif
    470 				mp->b_datap->db_type = M_ERROR;
    471 				mp->b_rptr = mp->b_datap->db_base;
    472 				*mp->b_rptr = EIO;
    473 				mp->b_wptr = mp->b_rptr + sizeof (char);
    474 				freemsg(mp->b_cont);
    475 				mp->b_cont = NULL;
    476 				qreply(WR(q), mp);
    477 				return (NULL);
    478 			}
    479 		}
    480 
    481 		/* O[n] = I[n] ^ V[n] */
    482 		*(optr++) = *(iptr++) ^
    483 		    tmi->enc_data.block[tmi->enc_data.bytes % CFB_BLKSZ];
    484 
    485 		tmi->enc_data.bytes++;
    486 		/*
    487 		 * Feedback the encrypted output as the input to next DES call.
    488 		 */
    489 		if (!(tmi->enc_data.bytes % CFB_BLKSZ)) {
    490 			char *dbptr = tmi->enc_data.block;
    491 			/*
    492 			 * Get the last bits of input from the previous
    493 			 * msg block that we haven't yet used as feedback input.
    494 			 */
    495 			if (savedbytes > 0) {
    496 				bcopy(tmi->enc_data.saveblock,
    497 				    dbptr, (size_t)savedbytes);
    498 				dbptr += savedbytes;
    499 			}
    500 
    501 			/*
    502 			 * Now copy the correct bytes from the current input
    503 			 * stream and update the 'lastoutput' ptr
    504 			 */
    505 			bcopy(lastoutput, dbptr,
    506 				(size_t)(CFB_BLKSZ - savedbytes));
    507 
    508 			lastoutput += (CFB_BLKSZ - savedbytes);
    509 			savedbytes = 0;
    510 		}
    511 	}
    512 	/*
    513 	 * If there are bytes of input here that we need in the next
    514 	 * block to build an ivec, save them off here.
    515 	 */
    516 	if (lastoutput < optr) {
    517 		bcopy(lastoutput,
    518 		    tmi->enc_data.saveblock + savedbytes,
    519 		    (uint_t)(optr - lastoutput));
    520 	}
    521 	return (mp);
    522 }
    523 
    524 /*
    525  * des_cfb_decrypt
    526  *
    527  * Decrypt the data in the mblk using DES in Cipher Feedback mode
    528  *
    529  * # bytes in == # bytes out, no padding, confounding, or hashing
    530  * is added.
    531  *
    532  */
    533 static mblk_t *
    534 des_cfb_decrypt(queue_t *q, struct tmodinfo *tmi, mblk_t *mp)
    535 {
    536 	uint_t len;
    537 	uint_t savedbytes;
    538 	char *iptr;
    539 	char *lastinput;
    540 	uint_t cp;
    541 
    542 	len = MBLKL(mp);
    543 
    544 	/* decrypted output goes into the new data buffer */
    545 	lastinput = iptr = (char *)mp->b_rptr;
    546 
    547 	savedbytes = tmi->dec_data.bytes % tmi->dec_data.blocklen;
    548 
    549 	/*
    550 	 * Save the input CFB_BLKSZ bytes at a time.
    551 	 * We are trying to decrypt in-place, but need to keep
    552 	 * a small sliding window of encrypted text to be
    553 	 * used to construct the feedback buffer.
    554 	 */
    555 	cp = ((tmi->dec_data.blocklen - savedbytes) > len ? len :
    556 		tmi->dec_data.blocklen - savedbytes);
    557 
    558 	bcopy(lastinput, tmi->dec_data.saveblock + savedbytes, cp);
    559 	savedbytes += cp;
    560 
    561 	lastinput += cp;
    562 
    563 	while (iptr < (char *)mp->b_wptr) {
    564 		/*
    565 		 * Do DES-ECB.
    566 		 * The first time this runs, the 'tmi->dec_data.block' will
    567 		 * contain the initialization vector that should have been
    568 		 * passed in with the SETUP ioctl.
    569 		 */
    570 		if (!(tmi->dec_data.bytes % CFB_BLKSZ)) {
    571 			int retval;
    572 			retval = kef_crypt(&tmi->dec_data,
    573 					tmi->dec_data.block,
    574 					CRYPTO_DATA_RAW,
    575 					tmi->dec_data.blocklen,
    576 					CRYPT_ENCRYPT);
    577 
    578 			if (retval != CRYPTO_SUCCESS) {
    579 #ifdef DEBUG
    580 				cmn_err(CE_WARN, "des_cfb_decrypt: kef_crypt "
    581 					"failed - status 0x%0x", retval);
    582 #endif
    583 				mp->b_datap->db_type = M_ERROR;
    584 				mp->b_rptr = mp->b_datap->db_base;
    585 				*mp->b_rptr = EIO;
    586 				mp->b_wptr = mp->b_rptr + sizeof (char);
    587 				freemsg(mp->b_cont);
    588 				mp->b_cont = NULL;
    589 				qreply(WR(q), mp);
    590 				return (NULL);
    591 			}
    592 		}
    593 
    594 		/*
    595 		 * To decrypt, XOR the input with the output from the DES call
    596 		 */
    597 		*(iptr++) ^= tmi->dec_data.block[tmi->dec_data.bytes %
    598 				CFB_BLKSZ];
    599 
    600 		tmi->dec_data.bytes++;
    601 
    602 		/*
    603 		 * Feedback the encrypted input for next DES call.
    604 		 */
    605 		if (!(tmi->dec_data.bytes % tmi->dec_data.blocklen)) {
    606 			char *dbptr = tmi->dec_data.block;
    607 			/*
    608 			 * Get the last bits of input from the previous block
    609 			 * that we haven't yet processed.
    610 			 */
    611 			if (savedbytes > 0) {
    612 				bcopy(tmi->dec_data.saveblock,
    613 				    dbptr, savedbytes);
    614 				dbptr += savedbytes;
    615 			}
    616 
    617 			savedbytes = 0;
    618 
    619 			/*
    620 			 * This block makes sure that our local
    621 			 * buffer of input data is full and can
    622 			 * be accessed from the beginning.
    623 			 */
    624 			if (lastinput < (char *)mp->b_wptr) {
    625 
    626 				/* How many bytes are left in the mblk? */
    627 				cp = (((char *)mp->b_wptr - lastinput) >
    628 					tmi->dec_data.blocklen ?
    629 					tmi->dec_data.blocklen :
    630 					(char *)mp->b_wptr - lastinput);
    631 
    632 				/* copy what we need */
    633 				bcopy(lastinput, tmi->dec_data.saveblock,
    634 					cp);
    635 
    636 				lastinput += cp;
    637 				savedbytes = cp;
    638 			}
    639 		}
    640 	}
    641 
    642 	return (mp);
    643 }
    644 
    645 /*
    646  * crc32_calc
    647  *
    648  * Compute a CRC32 checksum on the input
    649  */
    650 static int
    651 crc32_calc(uchar_t *buf, uchar_t *input, uint_t len)
    652 {
    653 	uint32_t crc;
    654 
    655 	CRC32(crc, input, len, 0, crc32_table);
    656 
    657 	buf[0] = (uchar_t)(crc & 0xff);
    658 	buf[1] = (uchar_t)((crc >> 8) & 0xff);
    659 	buf[2] = (uchar_t)((crc >> 16) & 0xff);
    660 	buf[3] = (uchar_t)((crc >> 24) & 0xff);
    661 
    662 	return (CRYPTO_SUCCESS);
    663 }
    664 
    665 static int
    666 kef_digest(crypto_mech_type_t digest_type,
    667 	uchar_t *input, uint_t inlen,
    668 	uchar_t *output, uint_t hashlen)
    669 {
    670 	iovec_t v1, v2;
    671 	crypto_data_t d1, d2;
    672 	crypto_mechanism_t mech;
    673 	int rv;
    674 
    675 	mech.cm_type = digest_type;
    676 	mech.cm_param = 0;
    677 	mech.cm_param_len = 0;
    678 
    679 	v1.iov_base = (void *)input;
    680 	v1.iov_len = inlen;
    681 
    682 	d1.cd_format = CRYPTO_DATA_RAW;
    683 	d1.cd_offset = 0;
    684 	d1.cd_length = v1.iov_len;
    685 	d1.cd_raw = v1;
    686 
    687 	v2.iov_base = (void *)output;
    688 	v2.iov_len = hashlen;
    689 
    690 	d2.cd_format = CRYPTO_DATA_RAW;
    691 	d2.cd_offset = 0;
    692 	d2.cd_length = v2.iov_len;
    693 	d2.cd_raw = v2;
    694 
    695 	rv = crypto_digest(&mech, &d1, &d2, NULL);
    696 
    697 	return (rv);
    698 }
    699 
    700 /*
    701  * sha1_calc
    702  *
    703  * Get a SHA1 hash on the input data.
    704  */
    705 static int
    706 sha1_calc(uchar_t *output, uchar_t *input, uint_t inlen)
    707 {
    708 	int rv;
    709 
    710 	rv = kef_digest(sha1_hash_mech, input, inlen, output, SHA1_HASHSIZE);
    711 
    712 	return (rv);
    713 }
    714 
    715 /*
    716  * Get an MD5 hash on the input data.
    717  * md5_calc
    718  *
    719  */
    720 static int
    721 md5_calc(uchar_t *output, uchar_t *input, uint_t inlen)
    722 {
    723 	int rv;
    724 
    725 	rv = kef_digest(md5_hash_mech, input, inlen, output, MD5_HASHSIZE);
    726 
    727 	return (rv);
    728 }
    729 
    730 /*
    731  * nfold
    732  * duplicate the functionality of the krb5_nfold function from
    733  * the userland kerberos mech.
    734  * This is needed to derive keys for use with 3DES/SHA1-HMAC
    735  * ciphers.
    736  */
    737 static void
    738 nfold(int inbits, uchar_t *in, int outbits, uchar_t *out)
    739 {
    740 	int a, b, c, lcm;
    741 	int byte, i, msbit;
    742 
    743 	inbits >>= 3;
    744 	outbits >>= 3;
    745 
    746 	/* first compute lcm(n,k) */
    747 	a = outbits;
    748 	b = inbits;
    749 
    750 	while (b != 0) {
    751 		c = b;
    752 		b = a%b;
    753 		a = c;
    754 	}
    755 
    756 	lcm = outbits*inbits/a;
    757 
    758 	/* now do the real work */
    759 
    760 	bzero(out, outbits);
    761 	byte = 0;
    762 
    763 	/*
    764 	 * Compute the msbit in k which gets added into this byte
    765 	 * first, start with the msbit in the first, unrotated byte
    766 	 * then, for each byte, shift to the right for each repetition
    767 	 * last, pick out the correct byte within that shifted repetition
    768 	 */
    769 	for (i = lcm-1; i >= 0; i--) {
    770 		msbit = (((inbits<<3)-1)
    771 			+(((inbits<<3)+13)*(i/inbits))
    772 			+((inbits-(i%inbits))<<3)) %(inbits<<3);
    773 
    774 		/* pull out the byte value itself */
    775 		byte += (((in[((inbits-1)-(msbit>>3))%inbits]<<8)|
    776 			(in[((inbits)-(msbit>>3))%inbits]))
    777 			>>((msbit&7)+1))&0xff;
    778 
    779 		/* do the addition */
    780 		byte += out[i%outbits];
    781 		out[i%outbits] = byte&0xff;
    782 
    783 		byte >>= 8;
    784 	}
    785 
    786 	/* if there's a carry bit left over, add it back in */
    787 	if (byte) {
    788 		for (i = outbits-1; i >= 0; i--) {
    789 			/* do the addition */
    790 			byte += out[i];
    791 			out[i] = byte&0xff;
    792 
    793 			/* keep around the carry bit, if any */
    794 			byte >>= 8;
    795 		}
    796 	}
    797 }
    798 
    799 #define	smask(step) ((1<<step)-1)
    800 #define	pstep(x, step) (((x)&smask(step))^(((x)>>step)&smask(step)))
    801 #define	parity_char(x) pstep(pstep(pstep((x), 4), 2), 1)
    802 
    803 /*
    804  * Duplicate the functionality of the "dk_derive_key" function
    805  * in the Kerberos mechanism.
    806  */
    807 static int
    808 derive_key(struct cipher_data_t *cdata, uchar_t *constdata,
    809 	int constlen, char *dkey, int keybytes,
    810 	int blocklen)
    811 {
    812 	int rv = 0;
    813 	int n = 0, i;
    814 	char *inblock;
    815 	char *rawkey;
    816 	char *zeroblock;
    817 	char *saveblock;
    818 
    819 	inblock = kmem_zalloc(blocklen, KM_SLEEP);
    820 	rawkey = kmem_zalloc(keybytes, KM_SLEEP);
    821 	zeroblock = kmem_zalloc(blocklen, KM_SLEEP);
    822 
    823 	if (constlen == blocklen)
    824 		bcopy(constdata, inblock, blocklen);
    825 	else
    826 		nfold(constlen * 8, constdata,
    827 			blocklen * 8, (uchar_t *)inblock);
    828 
    829 	/*
    830 	 * zeroblock is an IV of all 0's.
    831 	 *
    832 	 * The "block" section of the cdata record is used as the
    833 	 * IV for crypto operations in the kef_crypt function.
    834 	 *
    835 	 * We use 'block' as a generic IV data buffer because it
    836 	 * is attached to the stream state data and thus can
    837 	 * be used to hold information that must carry over
    838 	 * from processing of one mblk to another.
    839 	 *
    840 	 * Here, we save the current IV and replace it with
    841 	 * and empty IV (all 0's) for use when deriving the
    842 	 * keys.  Once the key derivation is done, we swap the
    843 	 * old IV back into place.
    844 	 */
    845 	saveblock = cdata->block;
    846 	cdata->block = zeroblock;
    847 
    848 	while (n < keybytes) {
    849 		rv = kef_crypt(cdata, inblock, CRYPTO_DATA_RAW,
    850 				blocklen, CRYPT_ENCRYPT);
    851 		if (rv != CRYPTO_SUCCESS) {
    852 			/* put the original IV block back in place */
    853 			cdata->block = saveblock;
    854 			cmn_err(CE_WARN, "failed to derive a key: %0x", rv);
    855 			goto cleanup;
    856 		}
    857 
    858 		if (keybytes - n < blocklen) {
    859 			bcopy(inblock, rawkey+n, (keybytes-n));
    860 			break;
    861 		}
    862 		bcopy(inblock, rawkey+n, blocklen);
    863 		n += blocklen;
    864 	}
    865 	/* put the original IV block back in place */
    866 	cdata->block = saveblock;
    867 
    868 	/* finally, make the key */
    869 	if (cdata->method == CRYPT_METHOD_DES3_CBC_SHA1) {
    870 		/*
    871 		 * 3DES key derivation requires that we make sure the
    872 		 * key has the proper parity.
    873 		 */
    874 		for (i = 0; i < 3; i++) {
    875 			bcopy(rawkey+(i*7), dkey+(i*8), 7);
    876 
    877 			/* 'dkey' is our derived key output buffer */
    878 			dkey[i*8+7] = (((dkey[i*8]&1)<<1) |
    879 					((dkey[i*8+1]&1)<<2) |
    880 					((dkey[i*8+2]&1)<<3) |
    881 					((dkey[i*8+3]&1)<<4) |
    882 					((dkey[i*8+4]&1)<<5) |
    883 					((dkey[i*8+5]&1)<<6) |
    884 					((dkey[i*8+6]&1)<<7));
    885 
    886 			for (n = 0; n < 8; n++) {
    887 				dkey[i*8 + n] &=  0xfe;
    888 				dkey[i*8 + n] |= 1^parity_char(dkey[i*8 + n]);
    889 			}
    890 		}
    891 	} else if (IS_AES_METHOD(cdata->method)) {
    892 		bcopy(rawkey, dkey, keybytes);
    893 	}
    894 cleanup:
    895 	kmem_free(inblock, blocklen);
    896 	kmem_free(zeroblock, blocklen);
    897 	kmem_free(rawkey, keybytes);
    898 	return (rv);
    899 }
    900 
    901 /*
    902  * create_derived_keys
    903  *
    904  * Algorithm for deriving a new key and an HMAC key
    905  * before computing the 3DES-SHA1-HMAC operation on the plaintext
    906  * This algorithm matches the work done by Kerberos mechanism
    907  * in userland.
    908  */
    909 static int
    910 create_derived_keys(struct cipher_data_t *cdata, uint32_t usage,
    911 		crypto_key_t *enckey, crypto_key_t *hmackey)
    912 {
    913 	uchar_t constdata[K5CLENGTH];
    914 	int keybytes;
    915 	int rv;
    916 
    917 	constdata[0] = (usage>>24)&0xff;
    918 	constdata[1] = (usage>>16)&0xff;
    919 	constdata[2] = (usage>>8)&0xff;
    920 	constdata[3] = usage & 0xff;
    921 	/* Use "0xAA" for deriving encryption key */
    922 	constdata[4] = 0xAA; /* from MIT Kerberos code */
    923 
    924 	enckey->ck_length = cdata->keylen * 8;
    925 	enckey->ck_format = CRYPTO_KEY_RAW;
    926 	enckey->ck_data = kmem_zalloc(cdata->keylen, KM_SLEEP);
    927 
    928 	switch (cdata->method) {
    929 		case CRYPT_METHOD_DES_CFB:
    930 		case CRYPT_METHOD_DES_CBC_NULL:
    931 		case CRYPT_METHOD_DES_CBC_MD5:
    932 		case CRYPT_METHOD_DES_CBC_CRC:
    933 			keybytes = 8;
    934 			break;
    935 		case CRYPT_METHOD_DES3_CBC_SHA1:
    936 			keybytes = CRYPT_DES3_KEYBYTES;
    937 			break;
    938 		case CRYPT_METHOD_ARCFOUR_HMAC_MD5:
    939 		case CRYPT_METHOD_ARCFOUR_HMAC_MD5_EXP:
    940 			keybytes = CRYPT_ARCFOUR_KEYBYTES;
    941 			break;
    942 		case CRYPT_METHOD_AES128:
    943 			keybytes = CRYPT_AES128_KEYBYTES;
    944 			break;
    945 		case CRYPT_METHOD_AES256:
    946 			keybytes = CRYPT_AES256_KEYBYTES;
    947 			break;
    948 	}
    949 
    950 	/* derive main crypto key */
    951 	rv = derive_key(cdata, constdata, sizeof (constdata),
    952 		enckey->ck_data, keybytes, cdata->blocklen);
    953 
    954 	if (rv == CRYPTO_SUCCESS) {
    955 
    956 		/* Use "0x55" for deriving mac key */
    957 		constdata[4] = 0x55;
    958 
    959 		hmackey->ck_length = cdata->keylen * 8;
    960 		hmackey->ck_format = CRYPTO_KEY_RAW;
    961 		hmackey->ck_data = kmem_zalloc(cdata->keylen, KM_SLEEP);
    962 
    963 		rv = derive_key(cdata, constdata, sizeof (constdata),
    964 				hmackey->ck_data, keybytes,
    965 				cdata->blocklen);
    966 	} else {
    967 		cmn_err(CE_WARN, "failed to derive crypto key: %02x", rv);
    968 	}
    969 
    970 	return (rv);
    971 }
    972 
    973 /*
    974  * Compute 3-DES crypto and HMAC.
    975  */
    976 static int
    977 kef_decr_hmac(struct cipher_data_t *cdata,
    978 	mblk_t *mp, int length,
    979 	char *hmac, int hmaclen)
    980 {
    981 	int rv = CRYPTO_FAILED;
    982 
    983 	crypto_mechanism_t encr_mech;
    984 	crypto_mechanism_t mac_mech;
    985 	crypto_data_t dd;
    986 	crypto_data_t mac;
    987 	iovec_t v1;
    988 
    989 	ASSERT(cdata != NULL);
    990 	ASSERT(mp != NULL);
    991 	ASSERT(hmac != NULL);
    992 
    993 	bzero(&dd, sizeof (dd));
    994 	dd.cd_format = CRYPTO_DATA_MBLK;
    995 	dd.cd_offset = 0;
    996 	dd.cd_length = length;
    997 	dd.cd_mp = mp;
    998 
    999 	v1.iov_base = hmac;
   1000 	v1.iov_len = hmaclen;
   1001 
   1002 	mac.cd_format = CRYPTO_DATA_RAW;
   1003 	mac.cd_offset = 0;
   1004 	mac.cd_length = hmaclen;
   1005 	mac.cd_raw = v1;
   1006 
   1007 	/*
   1008 	 * cdata->block holds the IVEC
   1009 	 */
   1010 	encr_mech.cm_type = cdata->mech_type;
   1011 	encr_mech.cm_param = cdata->block;
   1012 
   1013 	if (cdata->block != NULL)
   1014 		encr_mech.cm_param_len = cdata->blocklen;
   1015 	else
   1016 		encr_mech.cm_param_len = 0;
   1017 
   1018 	rv = crypto_decrypt(&encr_mech, &dd, &cdata->d_encr_key,
   1019 			cdata->enc_tmpl, NULL, NULL);
   1020 	if (rv != CRYPTO_SUCCESS) {
   1021 		cmn_err(CE_WARN, "crypto_decrypt failed: %0x", rv);
   1022 		return (rv);
   1023 	}
   1024 
   1025 	mac_mech.cm_type = sha1_hmac_mech;
   1026 	mac_mech.cm_param = NULL;
   1027 	mac_mech.cm_param_len = 0;
   1028 
   1029 	/*
   1030 	 * Compute MAC of the plaintext decrypted above.
   1031 	 */
   1032 	rv = crypto_mac(&mac_mech, &dd, &cdata->d_hmac_key,
   1033 			cdata->hmac_tmpl, &mac, NULL);
   1034 
   1035 	if (rv != CRYPTO_SUCCESS) {
   1036 		cmn_err(CE_WARN, "crypto_mac failed: %0x", rv);
   1037 	}
   1038 
   1039 	return (rv);
   1040 }
   1041 
   1042 /*
   1043  * Compute 3-DES crypto and HMAC.
   1044  */
   1045 static int
   1046 kef_encr_hmac(struct cipher_data_t *cdata,
   1047 	mblk_t *mp, int length,
   1048 	char *hmac, int hmaclen)
   1049 {
   1050 	int rv = CRYPTO_FAILED;
   1051 
   1052 	crypto_mechanism_t encr_mech;
   1053 	crypto_mechanism_t mac_mech;
   1054 	crypto_data_t dd;
   1055 	crypto_data_t mac;
   1056 	iovec_t v1;
   1057 
   1058 	ASSERT(cdata != NULL);
   1059 	ASSERT(mp != NULL);
   1060 	ASSERT(hmac != NULL);
   1061 
   1062 	bzero(&dd, sizeof (dd));
   1063 	dd.cd_format = CRYPTO_DATA_MBLK;
   1064 	dd.cd_offset = 0;
   1065 	dd.cd_length = length;
   1066 	dd.cd_mp = mp;
   1067 
   1068 	v1.iov_base = hmac;
   1069 	v1.iov_len = hmaclen;
   1070 
   1071 	mac.cd_format = CRYPTO_DATA_RAW;
   1072 	mac.cd_offset = 0;
   1073 	mac.cd_length = hmaclen;
   1074 	mac.cd_raw = v1;
   1075 
   1076 	/*
   1077 	 * cdata->block holds the IVEC
   1078 	 */
   1079 	encr_mech.cm_type = cdata->mech_type;
   1080 	encr_mech.cm_param = cdata->block;
   1081 
   1082 	if (cdata->block != NULL)
   1083 		encr_mech.cm_param_len = cdata->blocklen;
   1084 	else
   1085 		encr_mech.cm_param_len = 0;
   1086 
   1087 	mac_mech.cm_type = sha1_hmac_mech;
   1088 	mac_mech.cm_param = NULL;
   1089 	mac_mech.cm_param_len = 0;
   1090 
   1091 	rv = crypto_mac(&mac_mech, &dd, &cdata->d_hmac_key,
   1092 			cdata->hmac_tmpl, &mac, NULL);
   1093 
   1094 	if (rv !=