1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <pthread.h> 29 #include <stdlib.h> 30 #include <string.h> 31 #include <strings.h> 32 #include <sys/types.h> 33 #include <security/cryptoki.h> 34 #include <modes/modes.h> 35 #include <des_impl.h> 36 #include "softSession.h" 37 #include "softObject.h" 38 #include "softCrypt.h" 39 #include "softOps.h" 40 41 /* 42 * Allocate context for the active encryption or decryption operation, and 43 * generate DES or DES3 key schedule to speed up the operation. 44 */ 45 CK_RV 46 soft_des_crypt_init_common(soft_session_t *session_p, 47 CK_MECHANISM_PTR pMechanism, soft_object_t *key_p, 48 boolean_t encrypt) 49 { 50 51 size_t size; 52 soft_des_ctx_t *soft_des_ctx; 53 54 soft_des_ctx = calloc(1, sizeof (soft_des_ctx_t)); 55 if (soft_des_ctx == NULL) { 56 return (CKR_HOST_MEMORY); 57 } 58 59 /* Allocate key schedule for DES or DES3 based on key type. */ 60 if (key_p->key_type == CKK_DES) 61 soft_des_ctx->key_sched = des_alloc_keysched(&size, DES, 0); 62 else 63 soft_des_ctx->key_sched = des_alloc_keysched(&size, DES3, 0); 64 65 if (soft_des_ctx->key_sched == NULL) { 66 free(soft_des_ctx); 67 return (CKR_HOST_MEMORY); 68 } 69 70 soft_des_ctx->keysched_len = size; 71 soft_des_ctx->key_type = key_p->key_type; 72 73 (void) pthread_mutex_lock(&session_p->session_mutex); 74 if (encrypt) { 75 /* Called by C_EncryptInit. */ 76 session_p->encrypt.context = soft_des_ctx; 77 session_p->encrypt.mech.mechanism = pMechanism->mechanism; 78 } else { 79 /* Called by C_DecryptInit. */ 80 session_p->decrypt.context = soft_des_ctx; 81 session_p->decrypt.mech.mechanism = pMechanism->mechanism; 82 } 83 (void) pthread_mutex_unlock(&session_p->session_mutex); 84 85 /* 86 * If this is a non-sensitive key and it does NOT have 87 * a key schedule yet, then allocate one and expand it. 88 * Otherwise, if its a non-sensitive key, and it DOES have 89 * a key schedule already attached to it, just copy the 90 * pre-expanded schedule to the context and avoid the 91 * extra key schedule expansion operation. 92 */ 93 if (!(key_p->bool_attr_mask & SENSITIVE_BOOL_ON)) { 94 if (OBJ_KEY_SCHED(key_p) == NULL) { 95 void *ks; 96 (void) pthread_mutex_lock(&key_p->object_mutex); 97 if (OBJ_KEY_SCHED(key_p) == NULL) { 98 if (key_p->key_type == CKK_DES) 99 ks = des_alloc_keysched(&size, DES, 0); 100 else 101 ks = des_alloc_keysched(&size, DES3, 0); 102 if (ks == NULL) { 103 (void) pthread_mutex_unlock( 104 &key_p->object_mutex); 105 free(soft_des_ctx); 106 return (CKR_HOST_MEMORY); 107 } 108 /* Initialize key schedule for DES or DES3. */ 109 if (key_p->key_type == CKK_DES) 110 des_init_keysched( 111 OBJ_SEC(key_p)->sk_value, DES, ks); 112 else if (key_p->key_type == CKK_DES2) 113 /* 114 * DES3 encryption/decryption needs to 115 * support a DES2 key. 116 */ 117 des_init_keysched( 118 OBJ_SEC(key_p)->sk_value, DES2, ks); 119 else 120 des_init_keysched( 121 OBJ_SEC(key_p)->sk_value, DES3, ks); 122 123 OBJ_KEY_SCHED_LEN(key_p) = size; 124 OBJ_KEY_SCHED(key_p) = ks; 125 } 126 (void) pthread_mutex_unlock(&key_p->object_mutex); 127 } 128 129 /* Copy the pre-expanded key schedule from the key object */ 130 (void) memcpy(soft_des_ctx->key_sched, OBJ_KEY_SCHED(key_p), 131 OBJ_KEY_SCHED_LEN(key_p)); 132 soft_des_ctx->keysched_len = OBJ_KEY_SCHED_LEN(key_p); 133 } else { 134 /* for sensitive keys, we cannot cache the key schedule */ 135 if (key_p->key_type == CKK_DES) 136 des_init_keysched(OBJ_SEC(key_p)->sk_value, 137 DES, soft_des_ctx->key_sched); 138 else if (key_p->key_type == CKK_DES2) 139 /* 140 * DES3 encryption/decryption needs to 141 * support a DES2 key. 142 */ 143 des_init_keysched(OBJ_SEC(key_p)->sk_value, 144 DES2, soft_des_ctx->key_sched); 145 else 146 des_init_keysched(OBJ_SEC(key_p)->sk_value, 147 DES3, soft_des_ctx->key_sched); 148 } 149 150 return (CKR_OK); 151 } 152 153 154 /* 155 * soft_des_encrypt_common() 156 * 157 * Arguments: 158 * session_p: pointer to soft_session_t struct 159 * pData: pointer to the input data to be encrypted 160 * ulDataLen: length of the input data 161 * pEncrypted: pointer to the output data after encryption 162 * pulEncryptedLen: pointer to the length of the output data 163 * update: boolean flag indicates caller is soft_encrypt 164 * or soft_encrypt_update 165 * 166 * Description: 167 * This function calls the corresponding encrypt routine based 168 * on the mechanism. 169 * 170 * Returns: 171 * CKR_OK: success 172 * CKR_BUFFER_TOO_SMALL: the output buffer provided by application 173 * is too small 174 * CKR_FUNCTION_FAILED: encrypt function failed 175 * CKR_DATA_LEN_RANGE: the input data is not a multiple of blocksize 176 */ 177 CK_RV 178 soft_des_encrypt_common(soft_session_t *session_p, CK_BYTE_PTR pData, 179 CK_ULONG ulDataLen, CK_BYTE_PTR pEncrypted, 180 CK_ULONG_PTR pulEncryptedLen, boolean_t update) 181 { 182 int rc = 0; 183 CK_RV rv = CKR_OK; 184 soft_des_ctx_t *soft_des_ctx = 185 (soft_des_ctx_t *)session_p->encrypt.context; 186 des_ctx_t *des_ctx; 187 CK_MECHANISM_TYPE mechanism = session_p->encrypt.mech.mechanism; 188 CK_BYTE *in_buf = NULL; 189 CK_BYTE *out_buf = NULL; 190 CK_ULONG out_len; 191 CK_ULONG total_len; 192 CK_ULONG remain; 193 boolean_t pad_mechanism = B_FALSE; 194 195 pad_mechanism = (mechanism == CKM_DES_CBC_PAD || 196 mechanism == CKM_DES3_CBC_PAD); 197 /* 198 * DES only takes input length that is a multiple of blocksize 199 * for C_Encrypt function with the mechanism CKM_DES<n>_ECB or 200 * CKM_DES<n>_CBC. 201 * 202 * DES allows any input length for C_Encrypt function with the 203 * mechanism CKM_DES<n>_CBC_PAD and for C_EncryptUpdate function. 204 */ 205 if (!update && !pad_mechanism) { 206 if ((ulDataLen % DES_BLOCK_LEN) != 0) { 207 rv = CKR_DATA_LEN_RANGE; 208 goto cleanup; 209 } 210 } 211 212 if (!update) { 213 /* 214 * Called by C_Encrypt 215 */ 216 if (pad_mechanism) { 217 /* 218 * For CKM_DES<n>_CBC_PAD, compute output length to 219 * count for the padding. If the length of input 220 * data is a multiple of blocksize, then make output 221 * length to be the sum of the input length and 222 * one blocksize. Otherwise, output length will 223 * be rounded up to the next multiple of blocksize. 224 */ 225 out_len = DES_BLOCK_LEN * 226 (ulDataLen / DES_BLOCK_LEN + 1); 227 } else { 228 /* 229 * For non-padding mode, the output length will 230 * be same as the input length. 231 */ 232 out_len = ulDataLen; 233 } 234 235 /* 236 * If application asks for the length of the output buffer 237 * to hold the ciphertext? 238 */ 239 if (pEncrypted == NULL) { 240 *pulEncryptedLen = out_len; 241 return (CKR_OK); 242 } 243 244 /* Is the application-supplied buffer large enough? */ 245 if (*pulEncryptedLen < out_len) { 246 *pulEncryptedLen = out_len; 247 return (CKR_BUFFER_TOO_SMALL); 248 } 249 250 /* Encrypt pad bytes in a separate operation */ 251 if (pad_mechanism) { 252 out_len -= DES_BLOCK_LEN; 253 } 254 255 in_buf = pData; 256 out_buf = pEncrypted; 257 } else { 258 /* 259 * Called by C_EncryptUpdate 260 * 261 * Add the lengths of last remaining data and current 262 * plaintext together to get the total input length. 263 */ 264 total_len = soft_des_ctx->remain_len + ulDataLen; 265 266 /* 267 * If the total input length is less than one blocksize, 268 * or if the total input length is just one blocksize and 269 * the mechanism is CKM_DES<n>_CBC_PAD, we will need to delay 270 * encryption until when more data comes in next 271 * C_EncryptUpdate or when C_EncryptFinal is called. 272 */ 273 if ((total_len < DES_BLOCK_LEN) || 274 (pad_mechanism && (total_len == DES_BLOCK_LEN))) { 275 if (pData != NULL) { 276 /* 277 * Save input data and its length in 278 * the remaining buffer of DES context. 279 */ 280 (void) memcpy(soft_des_ctx->data + 281 soft_des_ctx->remain_len, pData, ulDataLen); 282 soft_des_ctx->remain_len += ulDataLen; 283 } 284 285 /* Set encrypted data length to 0. */ 286 *pulEncryptedLen = 0; 287 return (CKR_OK); 288 } 289 290 /* Compute the length of remaing data. */ 291 remain = total_len % DES_BLOCK_LEN; 292 293 /* 294 * Make sure that the output length is a multiple of 295 * blocksize. 296 */ 297 out_len = total_len - remain; 298 299 /* 300 * If application asks for the length of the output buffer 301 * to hold the ciphertext? 302 */ 303 if (pEncrypted == NULL) { 304 *pulEncryptedLen = out_len; 305 return (CKR_OK); 306 } 307 308 /* Is the application-supplied buffer large enough? */ 309 if (*pulEncryptedLen < out_len) { 310 *pulEncryptedLen = out_len; 311 return (CKR_BUFFER_TOO_SMALL); 312 } 313 314 if (soft_des_ctx->remain_len != 0) { 315 /* 316 * Copy last remaining data and current input data 317 * to the output buffer. 318 */ 319 (void) memmove(pEncrypted + soft_des_ctx->remain_len, 320 pData, out_len - soft_des_ctx->remain_len); 321 (void) memcpy(pEncrypted, soft_des_ctx->data, 322 soft_des_ctx->remain_len); 323 bzero(soft_des_ctx->data, soft_des_ctx->remain_len); 324 325 in_buf = pEncrypted; 326 } else { 327 in_buf = pData; 328 } 329 out_buf = pEncrypted; 330 } 331 332 /* 333 * Begin Encryption now. 334 */ 335 switch (mechanism) { 336 337 case CKM_DES_ECB: 338 case CKM_DES3_ECB: 339 { 340 341 ulong_t i; 342 uint8_t *tmp_inbuf; 343 uint8_t *tmp_outbuf; 344 345 for (i = 0; i < out_len; i += DES_BLOCK_LEN) { 346 tmp_inbuf = &in_buf[i]; 347 tmp_outbuf = &out_buf[i]; 348 /* Crunch one block of data for DES. */ 349 if (soft_des_ctx->key_type == CKK_DES) 350 (void) des_crunch_block( 351 soft_des_ctx->key_sched, 352 tmp_inbuf, tmp_outbuf, B_FALSE); 353 else 354 (void) des3_crunch_block( 355 soft_des_ctx->key_sched, 356 tmp_inbuf, tmp_outbuf, B_FALSE); 357 } 358 359 if (update) { 360 /* 361 * For encrypt update, if there is remaining 362 * data, save it and its length in the context. 363 */ 364 if (remain != 0) 365 (void) memcpy(soft_des_ctx->data, pData + 366 (ulDataLen - remain), remain); 367 soft_des_ctx->remain_len = remain; 368 } 369 370 *pulEncryptedLen = out_len; 371 break; 372 } 373 374 case CKM_DES_CBC: 375 case CKM_DES_CBC_PAD: 376 case CKM_DES3_CBC: 377 case CKM_DES3_CBC_PAD: 378 { 379 crypto_data_t out; 380 381 out.cd_format = CRYPTO_DATA_RAW; 382 out.cd_offset = 0; 383 out.cd_length = out_len; 384 out.cd_raw.iov_base = (char *)out_buf; 385 out.cd_raw.iov_len = out_len; 386 387 /* Encrypt multiple blocks of data. */ 388 rc = des_encrypt_contiguous_blocks( 389 (des_ctx_t *)soft_des_ctx->des_cbc, 390 (char *)in_buf, out_len, &out); 391 392 if (rc != 0) 393 goto encrypt_failed; 394 395 if (update) { 396 /* 397 * For encrypt update, if there is remaining data, 398 * save it and its length in the context. 399 */ 400 if (remain != 0) 401 (void) memcpy(soft_des_ctx->data, pData + 402 (ulDataLen - remain), remain); 403 soft_des_ctx->remain_len = remain; 404 } else if (pad_mechanism) { 405 /* 406 * Save the remainder of the input 407 * block in a temporary block because 408 * we don't want to overrun the input buffer 409 * by tacking on pad bytes. 410 */ 411 CK_BYTE tmpblock[DES_BLOCK_LEN]; 412 (void) memcpy(tmpblock, in_buf + out_len, 413 ulDataLen - out_len); 414 soft_add_pkcs7_padding(tmpblock + 415 (ulDataLen - out_len), 416 DES_BLOCK_LEN, ulDataLen - out_len); 417 418 out.cd_offset = out_len; 419 out.cd_length = DES_BLOCK_LEN; 420 out.cd_raw.iov_base = (char *)out_buf; 421 out.cd_raw.iov_len = out_len + DES_BLOCK_LEN; 422 423 /* Encrypt last block containing pad bytes. */ 424 rc = des_encrypt_contiguous_blocks( 425 (des_ctx_t *)soft_des_ctx->des_cbc, 426 (char *)tmpblock, DES_BLOCK_LEN, &out); 427 out_len += DES_BLOCK_LEN; 428 } 429 430 if (rc == 0) { 431 *pulEncryptedLen = out_len; 432 break; 433 } 434 encrypt_failed: 435 *pulEncryptedLen = 0; 436 rv = CKR_FUNCTION_FAILED; 437 goto cleanup; 438 439 } 440 } /* end switch */ 441 442 if (update) 443 return (CKR_OK); 444 445 /* 446 * The following code will be executed if the caller is 447 * soft_encrypt() or an error occurred. The encryption 448 * operation will be terminated so we need to do some cleanup. 449 */ 450 cleanup: 451 (void) pthread_mutex_lock(&session_p->session_mutex); 452 des_ctx = (des_ctx_t *)soft_des_ctx->des_cbc; 453 if (des_ctx != NULL) { 454 bzero(des_ctx->dc_keysched, des_ctx->dc_keysched_len); 455 free(soft_des_ctx->des_cbc); 456 } 457 458 bzero(soft_des_ctx->key_sched, soft_des_ctx->keysched_len); 459 free(soft_des_ctx->key_sched); 460 free(session_p->encrypt.context); 461 session_p->encrypt.context = NULL; 462 (void) pthread_mutex_unlock(&session_p->session_mutex); 463 464 return (rv); 465 } 466 467 468 /* 469 * soft_des_decrypt_common() 470 * 471 * Arguments: 472 * session_p: pointer to soft_session_t struct 473 * pEncrypted: pointer to the input data to be decrypted 474 * ulEncryptedLen: length of the input data 475 * pData: pointer to the output data 476 * pulDataLen: pointer to the length of the output data 477 * Update: boolean flag indicates caller is soft_decrypt 478 * or soft_decrypt_update 479 * 480 * Description: 481 * This function calls the corresponding decrypt routine based 482 * on the mechanism. 483 * 484 * Returns: 485 * CKR_OK: success 486 * CKR_BUFFER_TOO_SMALL: the output buffer provided by application 487 * is too small 488 * CKR_ENCRYPTED_DATA_LEN_RANGE: the input data is not a multiple 489 * of blocksize 490 * CKR_FUNCTION_FAILED: decrypt function failed 491 */ 492 CK_RV 493 soft_des_decrypt_common(soft_session_t *session_p, CK_BYTE_PTR pEncrypted, 494 CK_ULONG ulEncryptedLen, CK_BYTE_PTR pData, 495 CK_ULONG_PTR pulDataLen, boolean_t update) 496 { 497 498 int rc = 0; 499 CK_RV rv = CKR_OK; 500 soft_des_ctx_t *soft_des_ctx = 501 (soft_des_ctx_t *)session_p->decrypt.context; 502 des_ctx_t *des_ctx; 503 CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism; 504 CK_BYTE *in_buf = NULL; 505 CK_BYTE *out_buf = NULL; 506 CK_ULONG out_len; 507 CK_ULONG total_len; 508 CK_ULONG remain; 509 boolean_t pad_mechanism = B_FALSE; 510 511 pad_mechanism = (mechanism == CKM_DES_CBC_PAD || 512 mechanism == CKM_DES3_CBC_PAD); 513 /* 514 * DES only takes input length that is a multiple of 8 bytes 515 * for C_Decrypt function with the mechanism CKM_DES<n>_ECB, 516 * CKM_DES<n>_CBC or CKM_DES<n>_CBC_PAD. 517 * 518 * DES allows any input length for C_DecryptUpdate function. 519 */ 520 if (!update) { 521 /* 522 * Called by C_Decrypt 523 */ 524 if ((ulEncryptedLen % DES_BLOCK_LEN) != 0) { 525 rv = CKR_ENCRYPTED_DATA_LEN_RANGE; 526 goto cleanup; 527 } 528 529 /* 530 * If application asks for the length of the output buffer 531 * to hold the plaintext? 532 */ 533 if (pData == NULL) { 534 *pulDataLen = ulEncryptedLen; 535 return (CKR_OK); 536 } 537 538 /* Is the application-supplied buffer large enough? */ 539 if (!pad_mechanism) { 540 if (*pulDataLen < ulEncryptedLen) { 541 *pulDataLen = ulEncryptedLen; 542 return (CKR_BUFFER_TOO_SMALL); 543 } 544 545 /* Set output length same as input length. */ 546 out_len = ulEncryptedLen; 547 } else { 548 /* 549 * For CKM_DES<n>_CBC_PAD, we don't know how 550 * many bytes for padding at this time, so 551 * we'd assume one block was padded. 552 */ 553 if (*pulDataLen < (ulEncryptedLen - DES_BLOCK_LEN)) { 554 *pulDataLen = ulEncryptedLen - DES_BLOCK_LEN; 555 return (CKR_BUFFER_TOO_SMALL); 556 } 557 out_len = ulEncryptedLen - DES_BLOCK_LEN; 558 } 559 in_buf = pEncrypted; 560 out_buf = pData; 561 } else { 562 /* 563 * Called by C_DecryptUpdate 564 * 565 * Add the lengths of last remaining data and current 566 * input data together to get the total input length. 567 */ 568 total_len = soft_des_ctx->remain_len + ulEncryptedLen; 569 570 /* 571 * If the total input length is less than one blocksize, 572 * or if the total input length is just one blocksize and 573 * the mechanism is CKM_DES<n>_CBC_PAD, we will need to delay 574 * decryption until when more data comes in next 575 * C_DecryptUpdate or when C_DecryptFinal is called. 576 */ 577 if ((total_len < DES_BLOCK_LEN) || 578 (pad_mechanism && (total_len == DES_BLOCK_LEN))) { 579 if (pEncrypted != NULL) { 580 /* 581 * Save input data and its length in 582 * the remaining buffer of DES context. 583 */ 584 (void) memcpy(soft_des_ctx->data + 585 soft_des_ctx->remain_len, 586 pEncrypted, ulEncryptedLen); 587 soft_des_ctx->remain_len += ulEncryptedLen; 588 } 589 590 /* Set output data length to 0. */ 591 *pulDataLen = 0; 592 return (CKR_OK); 593 } 594 595 /* Compute the length of remaing data. */ 596 remain = total_len % DES_BLOCK_LEN; 597 598 /* 599 * Make sure that the output length is a multiple of 600 * blocksize. 601 */ 602 out_len = total_len - remain; 603 604 if (pad_mechanism) { 605 /* 606 * If the input data length is a multiple of 607 * blocksize, then save the last block of input 608 * data in the remaining buffer. C_DecryptFinal 609 * will handle this last block of data. 610 */ 611 if (remain == 0) { 612 remain = DES_BLOCK_LEN; 613 out_len -= DES_BLOCK_LEN; 614 } 615 } 616 617 /* 618 * If application asks for the length of the output buffer 619 * to hold the plaintext? 620 */ 621 if (pData == NULL) { 622 *pulDataLen = out_len; 623 return (CKR_OK); 624 } 625 626 /* 627 * Is the application-supplied buffer large enough? 628 */ 629 if (*pulDataLen < out_len) { 630 *pulDataLen = out_len; 631 return (CKR_BUFFER_TOO_SMALL); 632 } 633 634 if (soft_des_ctx->remain_len != 0) { 635 /* 636 * Copy last remaining data and current input data 637 * to the output buffer. 638 */ 639 (void) memmove(pData + soft_des_ctx->remain_len, 640 pEncrypted, out_len - soft_des_ctx->remain_len); 641 (void) memcpy(pData, soft_des_ctx->data, 642 soft_des_ctx->remain_len); 643 bzero(soft_des_ctx->data, soft_des_ctx->remain_len); 644 645 in_buf = pData; 646 } else { 647 in_buf = pEncrypted; 648 } 649 out_buf = pData; 650 } 651 652 /* 653 * Begin Decryption. 654 */ 655 switch (mechanism) { 656 657 case CKM_DES_ECB: 658 case CKM_DES3_ECB: 659 { 660 uint8_t *tmp_inbuf; 661 uint8_t *tmp_outbuf; 662 ulong_t i; 663 664 for (i = 0; i < out_len; i += DES_BLOCK_LEN) { 665 tmp_inbuf = &in_buf[i]; 666 tmp_outbuf = &out_buf[i]; 667 /* Crunch one block of data for DES. */ 668 if (soft_des_ctx->key_type == CKK_DES) 669 (void) des_crunch_block( 670 soft_des_ctx->key_sched, 671 tmp_inbuf, tmp_outbuf, B_TRUE); 672 else 673 (void) des3_crunch_block( 674 soft_des_ctx->key_sched, 675 tmp_inbuf, tmp_outbuf, B_TRUE); 676 } 677 678 if (update) { 679 /* 680 * For decrypt update, if there is remaining 681 * data, save it and its length in the context. 682 */ 683 if (remain != 0) 684 (void) memcpy(soft_des_ctx->data, pEncrypted + 685 (ulEncryptedLen - remain), remain); 686 soft_des_ctx->remain_len = remain; 687 } 688 689 *pulDataLen = out_len; 690 break; 691 } 692 693 case CKM_DES_CBC: 694 case CKM_DES_CBC_PAD: 695 case CKM_DES3_CBC: 696 case CKM_DES3_CBC_PAD: 697 { 698 crypto_data_t out; 699 CK_ULONG rem_len; 700 uint8_t last_block[DES_BLOCK_LEN]; 701 702 out.cd_format = CRYPTO_DATA_RAW; 703 out.cd_offset = 0; 704 out.cd_length = out_len; 705 out.cd_raw.iov_base = (char *)out_buf; 706 out.cd_raw.iov_len = out_len; 707 708 /* Decrypt multiple blocks of data. */ 709 rc = des_decrypt_contiguous_blocks( 710 (des_ctx_t *)soft_des_ctx->des_cbc, 711 (char *)in_buf, out_len, &out); 712 713 if (rc != 0) 714 goto decrypt_failed; 715 716 if (pad_mechanism && !update) { 717 /* Decrypt last block containing pad bytes. */ 718 out.cd_offset = 0; 719 out.cd_length = DES_BLOCK_LEN; 720 out.cd_raw.iov_base = (char *)last_block; 721 out.cd_raw.iov_len = DES_BLOCK_LEN; 722 723 /* Decrypt last block containing pad bytes. */ 724 rc = des_decrypt_contiguous_blocks( 725 (des_ctx_t *)soft_des_ctx->des_cbc, 726 (char *)in_buf + out_len, DES_BLOCK_LEN, &out); 727 728 if (rc != 0) 729 goto decrypt_failed; 730 731 /* 732 * Remove padding bytes after decryption of 733 * ciphertext block to produce the original 734 * plaintext. 735 */ 736 rv = soft_remove_pkcs7_padding(last_block, 737 DES_BLOCK_LEN, &rem_len, DES_BLOCK_LEN); 738 if (rv == CKR_OK) { 739 if (rem_len != 0) 740 (void) memcpy(out_buf + out_len, 741 last_block, rem_len); 742 *pulDataLen = out_len + rem_len; 743 } else { 744 *pulDataLen = 0; 745 goto cleanup; 746 } 747 } else { 748 *pulDataLen = out_len; 749 } 750 751 if (update) { 752 /* 753 * For decrypt update, if there is remaining data, 754 * save it and its length in the context. 755 */ 756 if (remain != 0) 757 (void) memcpy(soft_des_ctx->data, pEncrypted + 758 (ulEncryptedLen - remain), remain); 759 soft_des_ctx->remain_len = remain; 760 } 761 762 if (rc == 0) 763 break; 764 decrypt_failed: 765 *pulDataLen = 0; 766 rv = CKR_FUNCTION_FAILED; 767 goto cleanup; 768 } 769 } /* end switch */ 770 771 if (update) 772 return (CKR_OK); 773 774 /* 775 * The following code will be executed if the caller is 776 * soft_decrypt() or an error occurred. The decryption 777 * operation will be terminated so we need to do some cleanup. 778 */ 779 cleanup: 780 (void) pthread_mutex_lock(&session_p->session_mutex); 781 des_ctx = (des_ctx_t *)soft_des_ctx->des_cbc; 782 if (des_ctx != NULL) { 783 bzero(des_ctx->dc_keysched, des_ctx->dc_keysched_len); 784 free(soft_des_ctx->des_cbc); 785 } 786 787 bzero(soft_des_ctx->key_sched, soft_des_ctx->keysched_len); 788 free(soft_des_ctx->key_sched); 789 free(session_p->decrypt.context); 790 session_p->decrypt.context = NULL; 791 (void) pthread_mutex_unlock(&session_p->session_mutex); 792 793 return (rv); 794 } 795 796 797 /* 798 * Allocate and initialize a context for DES CBC mode of operation. 799 */ 800 void * 801 des_cbc_ctx_init(void *key_sched, size_t size, uint8_t *ivec, CK_KEY_TYPE type) 802 { 803 804 cbc_ctx_t *cbc_ctx; 805 806 if ((cbc_ctx = calloc(1, sizeof (cbc_ctx_t))) == NULL) 807 return (NULL); 808 809 cbc_ctx->cc_keysched = key_sched; 810 811 (void) memcpy(&cbc_ctx->cc_iv[0], ivec, DES_BLOCK_LEN); 812 813 cbc_ctx->cc_lastp = (uint8_t *)&cbc_ctx->cc_iv[0]; 814 cbc_ctx->cc_keysched_len = size; 815 if (type == CKK_DES) 816 cbc_ctx->cc_flags |= CBC_MODE; 817 else 818 cbc_ctx->cc_flags |= CBC_MODE | DES3_STRENGTH; 819 820 return (cbc_ctx); 821 822 } 823 824 /* 825 * Allocate and initialize DES contexts for both signing and encrypting, 826 * saving both context pointers in the session struct. For general-length DES 827 * MAC, check the length in the parameter to see if it is in the right range. 828 */ 829 CK_RV 830 soft_des_sign_verify_init_common(soft_session_t *session_p, 831 CK_MECHANISM_PTR pMechanism, soft_object_t *key_p, boolean_t sign_op) 832 { 833 soft_des_ctx_t *soft_des_ctx; 834 CK_MECHANISM encrypt_mech; 835 CK_RV rv; 836 837 if ((key_p->class != CKO_SECRET_KEY) || (key_p->key_type != CKK_DES)) { 838 return (CKR_KEY_TYPE_INCONSISTENT); 839 } 840 841 /* allocate memory for the sign/verify context */ 842 soft_des_ctx = malloc(sizeof (soft_des_ctx_t)); 843 if (soft_des_ctx == NULL) { 844 return (CKR_HOST_MEMORY); 845 } 846 847 soft_des_ctx->key_type = key_p->key_type; 848 849 /* initialization vector is zero for DES MAC */ 850 bzero(soft_des_ctx->ivec, DES_BLOCK_LEN); 851 852 switch (pMechanism->mechanism) { 853 854 case CKM_DES_MAC_GENERAL: 855 856 if (pMechanism->ulParameterLen != 857 sizeof (CK_MAC_GENERAL_PARAMS)) { 858 free(soft_des_ctx); 859 return (CKR_MECHANISM_PARAM_INVALID); 860 } 861 862 if (*(CK_MAC_GENERAL_PARAMS *)pMechanism->pParameter > 863 DES_BLOCK_LEN) { 864 free(soft_des_ctx); 865 return (CKR_MECHANISM_PARAM_INVALID); 866 } 867 868 soft_des_ctx->mac_len = *((CK_MAC_GENERAL_PARAMS_PTR) 869 pMechanism->pParameter); 870 871 /*FALLTHRU*/ 872 case CKM_DES_MAC: 873 874 /* 875 * For non-general DES MAC, output is always half as 876 * large as block size 877 */ 878 if (pMechanism->mechanism == CKM_DES_MAC) { 879 soft_des_ctx->mac_len = DES_MAC_LEN; 880 } 881 882 /* allocate a context for DES encryption */ 883 encrypt_mech.mechanism = CKM_DES_CBC_PAD; 884 encrypt_mech.pParameter = (void *)soft_des_ctx->ivec; 885 encrypt_mech.ulParameterLen = DES_BLOCK_LEN; 886 rv = soft_encrypt_init_internal(session_p, &encrypt_mech, 887 key_p); 888 if (rv != CKR_OK) { 889 free(soft_des_ctx); 890 return (rv); 891 } 892 893 (void) pthread_mutex_lock(&session_p->session_mutex); 894 895 if (sign_op) { 896 session_p->sign.context = soft_des_ctx; 897 session_p->sign.mech.mechanism = pMechanism->mechanism; 898 } else { 899 session_p->verify.context = soft_des_ctx; 900 session_p->verify.mech.mechanism = 901 pMechanism->mechanism; 902 } 903 904 (void) pthread_mutex_unlock(&session_p->session_mutex); 905 906 break; 907 } 908 return (CKR_OK); 909 } 910 911 /* 912 * Called by soft_sign(), soft_sign_final(), soft_verify() or 913 * soft_verify_final(). 914 */ 915 CK_RV 916 soft_des_sign_verify_common(soft_session_t *session_p, CK_BYTE_PTR pData, 917 CK_ULONG ulDataLen, CK_BYTE_PTR pSigned, CK_ULONG_PTR pulSignedLen, 918 boolean_t sign_op, boolean_t Final) 919 { 920 soft_des_ctx_t *soft_des_ctx_sign_verify; 921 soft_des_ctx_t *soft_des_ctx_encrypt; 922 CK_RV rv; 923 CK_BYTE *pEncrypted = NULL; 924 CK_ULONG ulEncryptedLen = 0; 925 uint8_t remainder; 926 CK_BYTE last_block[DES_BLOCK_LEN]; 927 des_ctx_t *des_ctx = NULL; 928 929 if (sign_op) { 930 soft_des_ctx_sign_verify = 931 (soft_des_ctx_t *)session_p->sign.context; 932 933 if (soft_des_ctx_sign_verify->mac_len == 0) { 934 *pulSignedLen = 0; 935 goto clean_exit; 936 } 937 938 /* Application asks for the length of the output buffer. */ 939 if (pSigned == NULL) { 940 *pulSignedLen = soft_des_ctx_sign_verify->mac_len; 941 return (CKR_OK); 942 } 943 944 /* Is the application-supplied buffer large enough? */ 945 if (*pulSignedLen < soft_des_ctx_sign_verify->mac_len) { 946 *pulSignedLen = soft_des_ctx_sign_verify->mac_len; 947 return (CKR_BUFFER_TOO_SMALL); 948 } 949 } else { 950 soft_des_ctx_sign_verify = 951 (soft_des_ctx_t *)session_p->verify.context; 952 } 953 954 if (Final) { 955 soft_des_ctx_encrypt = 956 (soft_des_ctx_t *)session_p->encrypt.context; 957 958 /* 959 * If there is data left in the buffer from a previous 960 * SignUpdate() call, pass enough zeroed data to a 961 * soft_sign_update call to pad the remainder 962 */ 963 if (soft_des_ctx_encrypt->remain_len != 0) { 964 bzero(last_block, DES_BLOCK_LEN); 965 ulEncryptedLen = DES_BLOCK_LEN; 966 967 /* 968 * By passing a buffer to soft_encrypt_final, 969 * we force it to pad the remaining block 970 * and encrypt it. 971 */ 972 rv = soft_encrypt_final(session_p, last_block, 973 &ulEncryptedLen); 974 if (rv != CKR_OK) { 975 goto clean_exit; 976 } 977 } else { 978 /* 979 * The last block of enciphered data is stored in: 980 * soft_des_ctx_encrypt->des_cbc->des_ctx->dc_lastp 981 * Copy that data to last_block 982 */ 983 soft_des_ctx_encrypt = 984 (soft_des_ctx_t *)session_p->encrypt.context; 985 des_ctx = (des_ctx_t *)soft_des_ctx_encrypt->des_cbc; 986 (void) memcpy(last_block, des_ctx->dc_lastp, 987 DES_BLOCK_LEN); 988 989 /* 990 * Passing a NULL output buffer here 991 * forces the routine to just return. 992 */ 993 rv = soft_encrypt_final(session_p, NULL, 994 &ulEncryptedLen); 995 } 996 997 } else { 998 /* 999 * If the input length is not multiple of block size, then 1000 * determine the correct encrypted data length by rounding 1001 */ 1002 remainder = ulDataLen % DES_BLOCK_LEN; 1003 /* 1004 * Because we always use DES_CBC_PAD mechanism 1005 * for sign/verify operations, the input will 1006 * be padded to the next 8 byte boundary. 1007 * Adjust the length fields here accordingly. 1008 */ 1009 ulEncryptedLen = ulDataLen + (DES_BLOCK_LEN - remainder); 1010 1011 pEncrypted = malloc(sizeof (CK_BYTE) * ulEncryptedLen); 1012 if (pEncrypted == NULL) { 1013 rv = CKR_HOST_MEMORY; 1014 goto clean_exit; 1015 } 1016 1017 /* 1018 * Pad the last block with zeros by copying pData into a zeroed 1019 * pEncrypted. Then pass pEncrypted into soft_encrypt as input 1020 */ 1021 bzero(pEncrypted, ulEncryptedLen); 1022 (void) memcpy(pEncrypted, pData, ulDataLen); 1023 1024 rv = soft_encrypt(session_p, pEncrypted, ulDataLen, 1025 pEncrypted, &ulEncryptedLen); 1026 (void) memcpy(last_block, 1027 &pEncrypted[ulEncryptedLen - DES_BLOCK_LEN], DES_BLOCK_LEN); 1028 } 1029 1030 if (rv == CKR_OK) { 1031 *pulSignedLen = soft_des_ctx_sign_verify->mac_len; 1032 1033 /* the leftmost mac_len bytes of last_block is our MAC */ 1034 (void) memcpy(pSigned, last_block, *pulSignedLen); 1035 } 1036 1037 clean_exit: 1038 1039 (void) pthread_mutex_lock(&session_p->session_mutex); 1040 1041 /* soft_encrypt_common() has freed the encrypt context */ 1042 if (sign_op) { 1043 free(session_p->sign.context); 1044 session_p->sign.context = NULL; 1045 } else { 1046 free(session_p->verify.context); 1047 session_p->verify.context = NULL; 1048 } 1049 session_p->encrypt.flags = 0; 1050 1051 (void) pthread_mutex_unlock(&session_p->session_mutex); 1052 1053 if (pEncrypted) { 1054 free(pEncrypted); 1055 } 1056 1057 return (rv); 1058 } 1059 1060 /* 1061 * Called by soft_sign_update() 1062 */ 1063 CK_RV 1064 soft_des_mac_sign_verify_update(soft_session_t *session_p, CK_BYTE_PTR pPart, 1065 CK_ULONG ulPartLen) 1066 { 1067 /* 1068 * The DES MAC is calculated by taking the specified number of 1069 * left-most bytes within the last block of 1070 * encrypted data, while the context of the multi-part 1071 * encryption stores the block necessary for XORing with the 1072 * input as per cipher block chaining . Therefore, none of the 1073 * intermediary encrypted blocks of data are necessary for 1074 * the DES MAC, and we can create a placeholder local buffer 1075 * for the encrypted data, which is immediately throw away. 1076 */ 1077 1078 soft_des_ctx_t *soft_des_ctx_encrypt; 1079 CK_BYTE *pEncrypted = NULL; 1080 CK_ULONG ulEncryptedLen; 1081 CK_ULONG total_len; 1082 uint8_t remainder; 1083 CK_RV rv; 1084 1085 soft_des_ctx_encrypt = (soft_des_ctx_t *)session_p->encrypt.context; 1086 1087 /* Avoid the malloc if we won't be encrypting any data */ 1088 total_len = soft_des_ctx_encrypt->remain_len + ulPartLen; 1089 1090 if (total_len < DES_BLOCK_LEN) { 1091 rv = soft_encrypt_update(session_p, pPart, ulPartLen, NULL, 1092 &ulEncryptedLen); 1093 } else { 1094 remainder = ulPartLen % DES_BLOCK_LEN; 1095 1096 /* round up to the nearest multiple of block size */ 1097 ulEncryptedLen = ulPartLen + (DES_BLOCK_LEN - remainder); 1098 pEncrypted = malloc(sizeof (CK_BYTE) * ulEncryptedLen); 1099 1100 if (pEncrypted != NULL) { 1101 rv = soft_encrypt_update(session_p, pPart, ulPartLen, 1102 pEncrypted, &ulEncryptedLen); 1103 free(pEncrypted); 1104 } else { 1105 rv = CKR_HOST_MEMORY; 1106 } 1107 } 1108 return (rv); 1109 } 1110