1 
   2 /*
   3  * CDDL HEADER START
   4  *
   5  * The contents of this file are subject to the terms of the
   6  * Common Development and Distribution License (the "License").
   7  * You may not use this file except in compliance with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 
  23 /*
  24  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  25  * Use is subject to license terms.
  26  */
  27 
  28 #pragma ident   "%Z%%M% %I%     %E% SMI"
  29 
  30 /*
  31  * Deimos - cryptographic acceleration based upon Broadcom 582x.
  32  */
  33 
  34 #include <sys/types.h>
  35 #include <sys/ddi.h>
  36 #include <sys/sunddi.h>
  37 #include <sys/kmem.h>
  38 #include <sys/note.h>
  39 #include <sys/crypto/common.h>
  40 #include <sys/crypto/spi.h>
  41 #include <sys/crypto/dca.h>
  42 
  43 /*
  44  * 3DES implementation.
  45  */
  46 
  47 static int dca_3desstart(dca_t *, uint32_t, dca_request_t *);
  48 static void dca_3desdone(dca_request_t *, int);
  49 
  50 
  51 int
  52 dca_3des(crypto_ctx_t *ctx, crypto_data_t *in,
  53     crypto_data_t *out, crypto_req_handle_t req, int flags)
  54 {
  55         int                     len;
  56         int                     rv;
  57         dca_request_t           *reqp = ctx->cc_provider_private;
  58         dca_request_t           *des_ctx = ctx->cc_provider_private;
  59         dca_t                   *dca = ctx->cc_provider;
  60         crypto_data_t           *nin = &reqp->dr_ctx.in_dup;
  61 
  62         len = dca_length(in);
  63         if (len % DESBLOCK) {
  64                 DBG(dca, DWARN, "input not an integral number of DES blocks");
  65                 (void) dca_free_context(ctx);
  66                 if (flags & DR_DECRYPT) {
  67                         return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
  68                 } else {
  69                         return (CRYPTO_DATA_LEN_RANGE);
  70                 }
  71         }
  72 
  73         /*
  74          * If cd_miscdata non-null then this contains the IV.
  75          */
  76         if (in->cd_miscdata != NULL) {
  77                 uchar_t *p = (uchar_t *)in->cd_miscdata;
  78                 des_ctx->dr_ctx.iv[0] = p[0]<<24 | p[1]<<16 | p[2]<<8 | p[3];
  79                 des_ctx->dr_ctx.iv[1] = p[4]<<24 | p[5]<<16 | p[6]<<8 | p[7];
  80         }
  81 
  82         if (len > dca_length(out)) {
  83                 DBG(dca, DWARN, "inadequate output space (need %d, got %d)",
  84                     len, dca_length(out));
  85                 out->cd_length = len;
  86                 /* Do not free the context since the app will call again */
  87                 return (CRYPTO_BUFFER_TOO_SMALL);
  88         }
  89 
  90         if ((rv = dca_verifyio(in, out)) != CRYPTO_SUCCESS) {
  91                 (void) dca_free_context(ctx);
  92                 return (rv);
  93         }
  94 
  95         /* special handling for null-sized input buffers */
  96         if (len == 0) {
  97                 out->cd_length = 0;
  98                 (void) dca_free_context(ctx);
  99                 return (CRYPTO_SUCCESS);
 100         }
 101 
 102         /*
 103          * Make a local copy of the input crypto_data_t structure. This
 104          * allows it to be manipulated locally and for dealing with in-place
 105          * data (ie in == out). Note that "nin" has been pre-allocated,
 106          * and only fields are copied, not actual data.
 107          */
 108         if ((rv = dca_dupcrypto(in, nin)) != CRYPTO_SUCCESS) {
 109                 (void) dca_free_context(ctx);
 110                 return (rv);
 111         }
 112 
 113         /* Set output to zero ready to take the processed data */
 114         out->cd_length = 0;
 115 
 116         reqp->dr_kcf_req = req;
 117         reqp->dr_in = nin;
 118         reqp->dr_out = out;
 119         reqp->dr_job_stat = DS_3DESJOBS;
 120         reqp->dr_byte_stat = DS_3DESBYTES;
 121 
 122         rv = dca_3desstart(dca, flags, reqp);
 123 
 124         /* Context will be freed in the kCF callback function otherwise */
 125         if (rv != CRYPTO_QUEUED && rv != CRYPTO_BUFFER_TOO_SMALL) {
 126                 (void) dca_free_context(ctx);
 127         }
 128         return (rv);
 129 }
 130 
 131 
 132 void
 133 dca_3desctxfree(void *arg)
 134 {
 135         crypto_ctx_t    *ctx = (crypto_ctx_t *)arg;
 136         dca_request_t   *des_ctx = ctx->cc_provider_private;
 137 
 138         if (des_ctx == NULL)
 139                 return;
 140 
 141         des_ctx->dr_ctx.atomic = 0;
 142         des_ctx->dr_ctx.ctx_cm_type = 0;
 143         ctx->cc_provider_private = NULL;
 144 
 145         if (des_ctx->destroy)
 146                 dca_destroyreq(des_ctx);
 147         else
 148                 /* Return it to the pool */
 149                 dca_freereq(des_ctx);
 150 }
 151 
 152 int
 153 dca_3desupdate(crypto_ctx_t *ctx, crypto_data_t *in,
 154     crypto_data_t *out, crypto_req_handle_t req, int flags)
 155 {
 156         int                     len;
 157         int                     rawlen;
 158         int                     rv;
 159         dca_request_t           *reqp = ctx->cc_provider_private;
 160         dca_request_t           *des_ctx = ctx->cc_provider_private;
 161         dca_t                   *dca = ctx->cc_provider;
 162         crypto_data_t           *nin = &reqp->dr_ctx.in_dup;
 163 
 164         rawlen = dca_length(in) + des_ctx->dr_ctx.residlen;
 165 
 166         len = ROUNDDOWN(rawlen, DESBLOCK);
 167         /*
 168          * If cd_miscdata non-null then this contains the IV.
 169          */
 170         if (in->cd_miscdata != NULL) {
 171                 uchar_t *p = (uchar_t *)in->cd_miscdata;
 172                 des_ctx->dr_ctx.iv[0] = p[0]<<24 | p[1]<<16 | p[2]<<8 | p[3];
 173                 des_ctx->dr_ctx.iv[1] = p[4]<<24 | p[5]<<16 | p[6]<<8 | p[7];
 174         }
 175 
 176         if (len > dca_length(out)) {
 177                 DBG(dca, DWARN, "not enough output space (need %d, got %d)",
 178                     len, dca_length(out));
 179                 out->cd_length = len;
 180                 /* Do not free the context since the app will call again */
 181                 return (CRYPTO_BUFFER_TOO_SMALL);
 182         }
 183 
 184         if ((rv = dca_verifyio(in, out)) != CRYPTO_SUCCESS) {
 185                 (void) dca_free_context(ctx);
 186                 return (rv);
 187         }
 188 
 189         reqp->dr_kcf_req = req;
 190 
 191         /*
 192          * From here on out, we are committed.
 193          */
 194 
 195         if (len == 0) {
 196                 /*
 197                  * No blocks being encrypted, so we just accumulate the
 198                  * input for the next pass and return.
 199                  */
 200                 if ((rv = dca_getbufbytes(in, 0,
 201                     (rawlen % DESBLOCK) - des_ctx->dr_ctx.residlen,
 202                     des_ctx->dr_ctx.resid + des_ctx->dr_ctx.residlen)) !=
 203                     CRYPTO_SUCCESS) {
 204                         DBG(dca, DWARN,
 205             "dca_3desupdate: dca_getbufbytes() failed for residual only pass");
 206                         dca_freereq(reqp);
 207                         return (rv);
 208                 }
 209                 des_ctx->dr_ctx.residlen = rawlen % DESBLOCK;
 210 
 211                 out->cd_length = 0;
 212                 /*
 213                  * Do not free the context here since it will be done
 214                  * in the final function
 215                  */
 216                 return (CRYPTO_SUCCESS);
 217         }
 218 
 219         /*
 220          * Set up rbuf for previous residual data.
 221          */
 222         if (des_ctx->dr_ctx.residlen) {
 223                 bcopy(des_ctx->dr_ctx.resid, des_ctx->dr_ctx.activeresid,
 224                     des_ctx->dr_ctx.residlen);
 225                 des_ctx->dr_ctx.activeresidlen = des_ctx->dr_ctx.residlen;
 226         }
 227 
 228         /*
 229          * Locate and save residual data for next encrypt_update.
 230          */
 231         if ((rv = dca_getbufbytes(in, len - des_ctx->dr_ctx.residlen,
 232             rawlen % DESBLOCK, des_ctx->dr_ctx.resid)) != CRYPTO_SUCCESS) {
 233                 DBG(dca, DWARN, "dca_3desupdate: dca_getbufbytes() failed");
 234                 (void) dca_free_context(ctx);
 235                 return (rv);
 236         }
 237 
 238         /* Calculate new residual length. */
 239         des_ctx->dr_ctx.residlen = rawlen % DESBLOCK;
 240 
 241         /*
 242          * Make a local copy of the input crypto_data_t structure. This
 243          * allows it to be manipulated locally and for dealing with in-place
 244          * data (ie in == out).
 245          */
 246         if ((rv = dca_dupcrypto(in, nin)) != CRYPTO_SUCCESS) {
 247                 (void) dca_free_context(ctx);
 248                 return (rv);
 249         }
 250 
 251         /* Set output to zero ready to take the processed data */
 252         out->cd_length = 0;
 253 
 254         reqp->dr_in = nin;
 255         reqp->dr_out = out;
 256         reqp->dr_job_stat = DS_3DESJOBS;
 257         reqp->dr_byte_stat = DS_3DESBYTES;
 258 
 259         rv = dca_3desstart(dca, flags, reqp);
 260 
 261         /*
 262          * As this is multi-part the context is cleared on success
 263          * (CRYPTO_QUEUED) in dca_3desfinal().
 264          */
 265 
 266         if (rv != CRYPTO_QUEUED && rv != CRYPTO_BUFFER_TOO_SMALL) {
 267                 (void) dca_free_context(ctx);
 268         }
 269         return (rv);
 270 }
 271 
 272 int
 273 dca_3desfinal(crypto_ctx_t *ctx, crypto_data_t *out, int mode)
 274 {
 275         dca_request_t   *des_ctx = ctx->cc_provider_private;
 276         dca_t           *dca = ctx->cc_provider;
 277         int             rv = CRYPTO_SUCCESS;
 278 
 279         ASSERT(ctx->cc_provider_private != NULL);
 280         /*
 281          * There must be no unprocessed ciphertext/plaintext.
 282          * This happens if the length of the last data is
 283          * not a multiple of the DES block length.
 284          */
 285         if (des_ctx->dr_ctx.residlen != 0) {
 286                 DBG(dca, DWARN, "dca_3desfinal: invalid nonzero residual");
 287                 if (mode & DR_DECRYPT) {
 288                         rv = CRYPTO_ENCRYPTED_DATA_LEN_RANGE;
 289                 } else {
 290                         rv = CRYPTO_DATA_LEN_RANGE;
 291                 }
 292         }
 293         (void) dca_free_context(ctx);
 294         out->cd_length = 0;
 295         return (rv);
 296 }
 297 
 298 int
 299 dca_3desatomic(crypto_provider_handle_t provider,
 300     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
 301     crypto_key_t *key, crypto_data_t *input, crypto_data_t *output,
 302     int kmflag, crypto_req_handle_t req, int mode)
 303 {
 304         crypto_ctx_t    ctx;    /* on the stack */
 305         int             rv;
 306 
 307         ctx.cc_provider = provider;
 308         ctx.cc_session = session_id;
 309 
 310         /*
 311          * Input must be a multiple of the block size. This test only
 312          * works for non-padded mechanisms when the blocksize is 2^N.
 313          */
 314         if ((dca_length(input) & (DESBLOCK - 1)) != 0) {
 315                 DBG(NULL, DWARN, "dca_3desatomic: input not multiple of BS");
 316                 if (mode & DR_DECRYPT) {
 317                         return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
 318                 } else {
 319                         return (CRYPTO_DATA_LEN_RANGE);
 320                 }
 321         }
 322 
 323         rv = dca_3desctxinit(&ctx, mechanism, key, kmflag, mode);
 324         if (rv != CRYPTO_SUCCESS) {
 325                 DBG(NULL, DWARN, "dca_3desatomic: dca_3desctxinit() failed");
 326                 return (rv);
 327         }
 328 
 329         /*
 330          * Set the atomic flag so that the hardware callback function
 331          * will free the context.
 332          */
 333         ((dca_request_t *)ctx.cc_provider_private)->dr_ctx.atomic = 1;
 334 
 335         /* check for inplace ops */
 336         if (input == output) {
 337                 ((dca_request_t *)ctx.cc_provider_private)->dr_flags
 338                     |= DR_INPLACE;
 339         }
 340 
 341         rv = dca_3des(&ctx, input, output, req, mode);
 342         if ((rv != CRYPTO_QUEUED) && (rv != CRYPTO_SUCCESS)) {
 343                 DBG(NULL, DWARN, "dca_3desatomic: dca_3des() failed");
 344                 output->cd_length = 0;
 345         }
 346 
 347         /*
 348          * The features of dca_3desfinal() are implemented within
 349          * dca_3desdone() due to the asynchronous nature of dca_3des().
 350          */
 351 
 352         /*
 353          * The context will be freed in the hardware callback function if it
 354          * is queued
 355          */
 356         if (rv != CRYPTO_QUEUED)
 357                 dca_3desctxfree(&ctx);
 358 
 359         return (rv);
 360 }
 361 
 362 int
 363 dca_3desstart(dca_t *dca, uint32_t flags, dca_request_t *reqp)
 364 {
 365         size_t          len;
 366         crypto_data_t   *in = reqp->dr_in;
 367         int             rv;
 368         dca_request_t   *ctx = reqp;
 369         uint32_t        iv[2];
 370 
 371         /*
 372          * Preconditions:
 373          * 1) in and out point to the "right" buffers.
 374          * 2) in->b_bcount - in->b_resid == initial offset
 375          * 3) likewise for out
 376          * 4) there is enough space in the output
 377          * 5) we perform a block for block encrypt
 378          */
 379         len = ctx->dr_ctx.activeresidlen + dca_length(in);
 380         len = ROUNDDOWN(min(len, MAXPACKET), DESBLOCK);
 381         reqp->dr_pkt_length = (uint16_t)len;
 382 
 383         /* collect IVs for this pass */
 384         iv[0] = ctx->dr_ctx.iv[0];
 385         iv[1] = ctx->dr_ctx.iv[1];
 386 
 387         /*
 388          * And also, for decrypt, collect the IV for the next pass.  For
 389          * decrypt, the IV must be collected BEFORE decryption, or else
 390          * we will lose it.  (For encrypt, we grab the IV AFTER encryption,
 391          * in dca_3desdone.
 392          */
 393         if (flags & DR_DECRYPT) {
 394                 uchar_t         ivstore[DESBLOCK];
 395                 uchar_t         *ivp = ivstore;
 396 
 397                 /* get last 8 bytes of ciphertext for IV of next op */
 398                 /*
 399                  * If we're processing only a DESBLOCKS worth of data
 400                  * and there is active residual present then it will be
 401                  * needed for the IV also.
 402                  */
 403                 if ((len == DESBLOCK) && ctx->dr_ctx.activeresidlen) {
 404                         /* Bring the active residual into play */
 405                         bcopy(ctx->dr_ctx.activeresid, ivstore,
 406                             ctx->dr_ctx.activeresidlen);
 407                         rv = dca_getbufbytes(in, 0,
 408                             DESBLOCK - ctx->dr_ctx.activeresidlen,
 409                             ivstore + ctx->dr_ctx.activeresidlen);
 410                 } else {
 411                         rv = dca_getbufbytes(in,
 412                             len - DESBLOCK - ctx->dr_ctx.activeresidlen,
 413                             DESBLOCK, ivstore);
 414                 }
 415 
 416                 if (rv != CRYPTO_SUCCESS) {
 417                         DBG(dca, DWARN,
 418                             "dca_3desstart: dca_getbufbytes() failed");
 419                         return (rv);
 420                 }
 421 
 422                 /* store as a pair of native 32-bit values */
 423                 ctx->dr_ctx.iv[0] =
 424                     ivp[0]<<24 | ivp[1]<<16 | ivp[2]<<8 | ivp[3];
 425                 ctx->dr_ctx.iv[1] =
 426                     ivp[4]<<24 | ivp[5]<<16 | ivp[6]<<8 | ivp[7];
 427         }
 428 
 429         /* For now we force a pullup.  Add direct DMA later. */
 430         reqp->dr_flags &= ~(DR_SCATTER | DR_GATHER);
 431         if ((len < dca_mindma) || (ctx->dr_ctx.activeresidlen > 0) ||
 432             dca_sgcheck(dca, reqp->dr_in, DCA_SG_CONTIG) ||
 433             dca_sgcheck(dca, reqp->dr_out, DCA_SG_WALIGN)) {
 434                 reqp->dr_flags |= DR_SCATTER | DR_GATHER;
 435         }
 436 
 437         /* Try to do direct DMA. */
 438         if (!(reqp->dr_flags & (DR_SCATTER | DR_GATHER))) {
 439                 if (dca_bindchains(reqp, len, len) == DDI_SUCCESS) {
 440                         reqp->dr_in->cd_offset += len;
 441                         reqp->dr_in->cd_length -= len;
 442                 } else {
 443                         DBG(dca, DWARN,
 444                             "dca_3desstart: dca_bindchains() failed");
 445                         return (CRYPTO_DEVICE_ERROR);
 446                 }
 447         }
 448 
 449         /* gather the data into the device */
 450         if (reqp->dr_flags & DR_GATHER) {
 451                 rv = dca_resid_gather(in, (char *)ctx->dr_ctx.activeresid,
 452                     &ctx->dr_ctx.activeresidlen, reqp->dr_ibuf_kaddr, len);
 453                 if (rv != CRYPTO_SUCCESS) {
 454                         DBG(dca, DWARN,
 455                             "dca_3desstart: dca_resid_gather() failed");
 456                         return (rv);
 457                 }
 458                 /*
 459                  * Setup for scattering the result back out
 460                  * The output buffer is a multi-entry chain for x86 and
 461                  * a single entry chain for Sparc.
 462                  * Use the actual length if the first entry is sufficient.
 463                  */
 464                 (void) ddi_dma_sync(reqp->dr_ibuf_dmah, 0, len,
 465                     DDI_DMA_SYNC_FORDEV);
 466                 if (dca_check_dma_handle(dca, reqp->dr_ibuf_dmah,
 467                     DCA_FM_ECLASS_NONE) != DDI_SUCCESS) {
 468                         reqp->destroy = TRUE;
 469                         return (CRYPTO_DEVICE_ERROR);
 470                 }
 471 
 472                 reqp->dr_in_paddr = reqp->dr_ibuf_head.dc_buffer_paddr;
 473                 reqp->dr_in_next = reqp->dr_ibuf_head.dc_next_paddr;
 474                 if (len > reqp->dr_ibuf_head.dc_buffer_length)
 475                         reqp->dr_in_len = reqp->dr_ibuf_head.dc_buffer_length;
 476                 else
 477                         reqp->dr_in_len = len;
 478         }
 479         /*
 480          * Setup for scattering the result back out
 481          * The output buffer is a multi-entry chain for x86 and
 482          * a single entry chain for Sparc.
 483          * Use the actual length if the first entry is sufficient.
 484          */
 485         if (reqp->dr_flags & DR_SCATTER) {
 486                 reqp->dr_out_paddr = reqp->dr_obuf_head.dc_buffer_paddr;
 487                 reqp->dr_out_next = reqp->dr_obuf_head.dc_next_paddr;
 488                 if (len > reqp->dr_obuf_head.dc_buffer_length)
 489                         reqp->dr_out_len = reqp->dr_obuf_head.dc_buffer_length;
 490                 else
 491                         reqp->dr_out_len = len;
 492         }
 493 
 494         reqp->dr_flags |= flags;
 495         reqp->dr_callback = dca_3desdone;
 496 
 497         /* write out the context structure */
 498         PUTCTX32(reqp, CTX_3DESIVHI, iv[0]);
 499         PUTCTX32(reqp, CTX_3DESIVLO, iv[1]);
 500 
 501         /* schedule the work by doing a submit */
 502         return (dca_start(dca, reqp, MCR1, 1));
 503 }
 504 
 505 void
 506 dca_3desdone(dca_request_t *reqp, int errno)
 507 {
 508         crypto_data_t   *out = reqp->dr_out;
 509         dca_request_t   *ctx = reqp;
 510         ASSERT(ctx != NULL);
 511 
 512         if (errno == CRYPTO_SUCCESS) {
 513                 size_t          off;
 514                 /*
 515                  * Save the offset: this has to be done *before* dca_scatter
 516                  * modifies the buffer.  We take the initial offset into the
 517                  * first buf, and add that to the total packet size to find
 518                  * the end of the packet.
 519                  */
 520                 off = dca_length(out) + reqp->dr_pkt_length - DESBLOCK;
 521 
 522                 if (reqp->dr_flags & DR_SCATTER) {
 523                         (void) ddi_dma_sync(reqp->dr_obuf_dmah, 0,
 524                             reqp->dr_out_len, DDI_DMA_SYNC_FORKERNEL);
 525                         if (dca_check_dma_handle(reqp->dr_dca,
 526                             reqp->dr_obuf_dmah, DCA_FM_ECLASS_NONE) !=
 527                             DDI_SUCCESS) {
 528                                 reqp->destroy = TRUE;
 529                                 errno = CRYPTO_DEVICE_ERROR;
 530                                 goto errout;
 531                         }
 532 
 533                         errno = dca_scatter(reqp->dr_obuf_kaddr,
 534                             reqp->dr_out, reqp->dr_out_len, 0);
 535                         if (errno != CRYPTO_SUCCESS) {
 536                                 DBG(NULL, DWARN,
 537                                     "dca_3desdone: dca_scatter() failed");
 538                                 goto errout;
 539                         }
 540 
 541                 } else {
 542                         /* we've processed some more data */
 543                         out->cd_length += reqp->dr_pkt_length;
 544                 }
 545 
 546 
 547                 /*
 548                  * For encryption only, we have to grab the IV for the
 549                  * next pass AFTER encryption.
 550                  */
 551                 if (reqp->dr_flags & DR_ENCRYPT) {
 552                         uchar_t         ivstore[DESBLOCK];
 553                         uchar_t         *iv = ivstore;
 554 
 555                         /* get last 8 bytes for IV of next op */
 556                         errno = dca_getbufbytes(out, off, DESBLOCK, iv);
 557                         if (errno != CRYPTO_SUCCESS) {
 558                                 DBG(NULL, DWARN,
 559                                     "dca_3desdone: dca_getbufbytes() failed");
 560                                 goto errout;
 561                         }
 562                         /* store as a pair of native 32-bit values */
 563                         ctx->dr_ctx.iv[0] =
 564                             iv[0]<<24 | iv[1]<<16 | iv[2]<<8 | iv[3];
 565                         ctx->dr_ctx.iv[1] =
 566                             iv[4]<<24 | iv[5]<<16 | iv[6]<<8 | iv[7];
 567                 }
 568 
 569                 /*
 570                  * If there is more to do, then reschedule another
 571                  * pass.
 572                  */
 573                 if (dca_length(reqp->dr_in) >= 8) {
 574                         errno = dca_3desstart(reqp->dr_dca, reqp->dr_flags,
 575                             reqp);
 576                         if (errno == CRYPTO_QUEUED) {
 577                                 return;
 578                         }
 579                 }
 580         }
 581 
 582 errout:
 583 
 584         /*
 585          * If this is an atomic operation perform the final function
 586          * tasks (equivalent to to dca_3desfinal()).
 587          */
 588         if (reqp->dr_ctx.atomic) {
 589                 if ((errno == CRYPTO_SUCCESS) && (ctx->dr_ctx.residlen != 0)) {
 590                         DBG(NULL, DWARN,
 591                             "dca_3desdone: invalid nonzero residual");
 592                         if (reqp->dr_flags & DR_DECRYPT) {
 593                                 errno = CRYPTO_ENCRYPTED_DATA_LEN_RANGE;
 594                         } else {
 595                                 errno = CRYPTO_DATA_LEN_RANGE;
 596                         }
 597                 }
 598         }
 599 
 600         ASSERT(reqp->dr_kcf_req != NULL);
 601         /* notify framework that request is completed */
 602         crypto_op_notification(reqp->dr_kcf_req, errno);
 603         DBG(NULL, DINTR,
 604             "dca_3desdone: returning %d to the kef via crypto_op_notification",
 605             errno);
 606 
 607         /* This has to be done after notifing the framework */
 608         if (reqp->dr_ctx.atomic) {
 609                 reqp->dr_context = NULL;
 610                 reqp->dr_ctx.atomic = 0;
 611                 reqp->dr_ctx.ctx_cm_type = 0;
 612                 if (reqp->destroy)
 613                         dca_destroyreq(reqp);
 614                 else
 615                         dca_freereq(reqp);
 616         }
 617 }
 618 
 619 /* ARGSUSED */
 620 int
 621 dca_3desctxinit(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
 622     crypto_key_t *key, int kmflag, int flags)
 623 {
 624         dca_request_t   *des_ctx;
 625         dca_t           *dca = ctx->cc_provider;
 626         uchar_t         *param;
 627         uchar_t         *value;
 628         size_t          paramsz;
 629         unsigned        len;
 630         int             i, j;
 631 
 632         paramsz = mechanism->cm_param_len;
 633         param = (uchar_t *)mechanism->cm_param;
 634         if ((paramsz != 0) && (paramsz != DES_IV_LEN)) {
 635                 DBG(NULL, DWARN,
 636                     "dca_3desctxinit: parameter(IV) length not %d (%d)",
 637                     DES_IV_LEN, paramsz);
 638                 return (CRYPTO_MECHANISM_PARAM_INVALID);
 639         }
 640 
 641         if ((des_ctx = dca_getreq(dca, MCR1, 1)) == NULL) {
 642                 dca_error(dca, "unable to allocate request for 3DES");
 643                 return (CRYPTO_HOST_MEMORY);
 644         }
 645         /*
 646          * Identify and store the IV as a pair of native 32-bit words.
 647          *
 648          * If cm_param == NULL then the IV comes from the cd_miscdata field
 649          * in the crypto_data structure.
 650          */
 651         if (param != NULL) {
 652                 ASSERT(paramsz == DES_IV_LEN);
 653                 des_ctx->dr_ctx.iv[0] = param[0]<<24 | param[1]<<16 |
 654                     param[2]<<8 | param[3];
 655                 des_ctx->dr_ctx.iv[1] = param[4]<<24 | param[5]<<16 |
 656                     param[6]<<8 | param[7];
 657         }
 658         des_ctx->dr_ctx.residlen = 0;
 659         des_ctx->dr_ctx.activeresidlen = 0;
 660         des_ctx->dr_ctx.ctx_cm_type = mechanism->cm_type;
 661         ctx->cc_provider_private = des_ctx;
 662 
 663         if (key->ck_format != CRYPTO_KEY_RAW) {
 664                 DBG(NULL, DWARN,
 665         "dca_3desctxinit: only raw crypto key type support with DES/3DES");
 666                 dca_3desctxfree(ctx);
 667                 return (CRYPTO_KEY_TYPE_INCONSISTENT);
 668         }
 669 
 670         len = key->ck_length;
 671         value = (uchar_t *)key->ck_data;
 672 
 673         if (flags & DR_TRIPLE) {
 674                 /* 3DES */
 675                 switch (len) {
 676                 case 192:
 677                         for (i = 0; i < 6; i++) {
 678                                 des_ctx->dr_ctx.key[i] = 0;
 679                                 for (j = 0; j < 4; j++) {
 680                                         des_ctx->dr_ctx.key[i] <<= 8;
 681                                         des_ctx->dr_ctx.key[i] |= *value;
 682                                         value++;
 683                                 }
 684                         }
 685                         break;
 686 
 687                 case 128:
 688                         for (i = 0; i < 4; i++) {
 689                                 des_ctx->dr_ctx.key[i] = 0;
 690                                 for (j = 0; j < 4; j++) {
 691                                         des_ctx->dr_ctx.key[i] <<= 8;
 692                                         des_ctx->dr_ctx.key[i] |= *value;
 693                                         value++;
 694                                 }
 695                         }
 696                         des_ctx->dr_ctx.key[4] = des_ctx->dr_ctx.key[0];
 697                         des_ctx->dr_ctx.key[5] = des_ctx->dr_ctx.key[1];
 698                         break;
 699 
 700                 default:
 701                         DBG(NULL, DWARN, "Incorrect 3DES keysize (%d)", len);
 702                         dca_3desctxfree(ctx);
 703                         return (CRYPTO_KEY_SIZE_RANGE);
 704                 }
 705         } else {
 706                 /* single DES */
 707                 if (len != 64) {
 708                         DBG(NULL, DWARN, "Incorrect DES keysize (%d)", len);
 709                         dca_3desctxfree(ctx);
 710                         return (CRYPTO_KEY_SIZE_RANGE);
 711                 }
 712                 des_ctx->dr_ctx.key[0] =
 713                     value[0]<<24 | value[1]<<16 | value[2]<<8 | value[3];
 714                 des_ctx->dr_ctx.key[1] =
 715                     value[4]<<24 | value[5]<<16 | value[6]<<8 | value[7];
 716                 /* for single des just repeat des key */
 717                 des_ctx->dr_ctx.key[4] =
 718                     des_ctx->dr_ctx.key[2] = des_ctx->dr_ctx.key[0];
 719                 des_ctx->dr_ctx.key[5] =
 720                     des_ctx->dr_ctx.key[3] = des_ctx->dr_ctx.key[1];
 721         }
 722 
 723         /*
 724          * Setup the context here so that we do not need to setup it up
 725          * for every update
 726          */
 727         PUTCTX16(des_ctx, CTX_LENGTH, CTX_3DES_LENGTH);
 728         PUTCTX16(des_ctx, CTX_CMD, CMD_3DES);
 729         PUTCTX32(des_ctx, CTX_3DESDIRECTION,
 730             flags & DR_ENCRYPT ? CTX_3DES_ENCRYPT : CTX_3DES_DECRYPT);
 731         PUTCTX32(des_ctx, CTX_3DESKEY1HI, des_ctx->dr_ctx.key[0]);
 732         PUTCTX32(des_ctx, CTX_3DESKEY1LO, des_ctx->dr_ctx.key[1]);
 733         PUTCTX32(des_ctx, CTX_3DESKEY2HI, des_ctx->dr_ctx.key[2]);
 734         PUTCTX32(des_ctx, CTX_3DESKEY2LO, des_ctx->dr_ctx.key[3]);
 735         PUTCTX32(des_ctx, CTX_3DESKEY3HI, des_ctx->dr_ctx.key[4]);
 736         PUTCTX32(des_ctx, CTX_3DESKEY3LO, des_ctx->dr_ctx.key[5]);
 737 
 738         return (CRYPTO_SUCCESS);
 739 }