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 } 740