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