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