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