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