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