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