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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <pthread.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <strings.h> 33 #include <sys/types.h> 34 #include <security/cryptoki.h> 35 #include <des_cbc_crypt.h> 36 #include <aes_cbc_crypt.h> 37 #include <arcfour.h> 38 #include "softSession.h" 39 #include "softObject.h" 40 #include "softOps.h" 41 #include "softCrypt.h" 42 #include "softRSA.h" 43 44 45 /* 46 * Remove padding bytes. 47 */ 48 CK_RV 49 soft_remove_pkcs7_padding(CK_BYTE *pData, CK_ULONG padded_len, 50 CK_ULONG *pulDataLen, int block_size) 51 { 52 53 CK_BYTE pad_value; 54 55 pad_value = pData[padded_len - 1]; 56 57 58 /* Make sure there is a valid padding value. */ 59 if ((pad_value == 0) || (pad_value > block_size)) 60 return (CKR_ENCRYPTED_DATA_INVALID); 61 62 *pulDataLen = padded_len - pad_value; 63 return (CKR_OK); 64 } 65 66 67 /* 68 * soft_decrypt_init() 69 * 70 * Arguments: 71 * session_p: pointer to soft_session_t struct 72 * pMechanism: pointer to CK_MECHANISM struct provided by application 73 * key_p: pointer to key soft_object_t struct 74 * 75 * Description: 76 * called by C_DecryptInit(). This function calls the corresponding 77 * decrypt init routine based on the mechanism. 78 * 79 * Returns: 80 * CKR_OK: success 81 * CKR_HOST_MEMORY: run out of system memory 82 * CKR_MECHANISM_PARAM_INVALID: invalid parameters in mechanism 83 * CKR_MECHANISM_INVALID: invalid mechanism type 84 * CKR_KEY_TYPE_INCONSISTENT: incorrect type of key to use 85 * with the specified mechanism 86 */ 87 CK_RV 88 soft_decrypt_init(soft_session_t *session_p, CK_MECHANISM_PTR pMechanism, 89 soft_object_t *key_p) 90 { 91 92 CK_RV rv; 93 94 switch (pMechanism->mechanism) { 95 96 case CKM_DES_ECB: 97 98 if (key_p->key_type != CKK_DES) { 99 return (CKR_KEY_TYPE_INCONSISTENT); 100 } 101 102 goto ecb_common; 103 104 case CKM_DES3_ECB: 105 106 if ((key_p->key_type != CKK_DES2) && 107 (key_p->key_type != CKK_DES3)) { 108 return (CKR_KEY_TYPE_INCONSISTENT); 109 } 110 111 ecb_common: 112 113 return (soft_des_crypt_init_common(session_p, pMechanism, 114 key_p, B_FALSE)); 115 116 case CKM_DES_CBC: 117 case CKM_DES_CBC_PAD: 118 119 if (key_p->key_type != CKK_DES) { 120 return (CKR_KEY_TYPE_INCONSISTENT); 121 } 122 123 goto cbc_common; 124 125 case CKM_DES3_CBC: 126 case CKM_DES3_CBC_PAD: 127 { 128 soft_des_ctx_t *soft_des_ctx; 129 130 if ((key_p->key_type != CKK_DES2) && 131 (key_p->key_type != CKK_DES3)) { 132 return (CKR_KEY_TYPE_INCONSISTENT); 133 } 134 135 cbc_common: 136 if ((pMechanism->pParameter == NULL) || 137 (pMechanism->ulParameterLen != DES_BLOCK_LEN)) { 138 return (CKR_MECHANISM_PARAM_INVALID); 139 } 140 141 rv = soft_des_crypt_init_common(session_p, pMechanism, 142 key_p, B_FALSE); 143 144 if (rv != CKR_OK) 145 return (rv); 146 147 (void) pthread_mutex_lock(&session_p->session_mutex); 148 149 soft_des_ctx = (soft_des_ctx_t *)session_p->decrypt.context; 150 /* Save Initialization Vector (IV) in the context. */ 151 (void) memcpy(soft_des_ctx->ivec, pMechanism->pParameter, 152 DES_BLOCK_LEN); 153 154 /* Allocate a context for DES cipher-block chaining. */ 155 soft_des_ctx->des_cbc = (void *)des_cbc_ctx_init( 156 soft_des_ctx->key_sched, soft_des_ctx->keysched_len, 157 soft_des_ctx->ivec, key_p->key_type); 158 159 if (soft_des_ctx->des_cbc == NULL) { 160 bzero(soft_des_ctx->key_sched, 161 soft_des_ctx->keysched_len); 162 free(soft_des_ctx->key_sched); 163 free(session_p->decrypt.context); 164 session_p->decrypt.context = NULL; 165 (void) pthread_mutex_unlock(&session_p->session_mutex); 166 return (CKR_HOST_MEMORY); 167 } 168 169 (void) pthread_mutex_unlock(&session_p->session_mutex); 170 171 return (rv); 172 } 173 case CKM_AES_ECB: 174 175 if (key_p->key_type != CKK_AES) { 176 return (CKR_KEY_TYPE_INCONSISTENT); 177 } 178 179 return (soft_aes_crypt_init_common(session_p, pMechanism, 180 key_p, B_FALSE)); 181 182 case CKM_AES_CBC: 183 case CKM_AES_CBC_PAD: 184 { 185 soft_aes_ctx_t *soft_aes_ctx; 186 187 if (key_p->key_type != CKK_AES) { 188 return (CKR_KEY_TYPE_INCONSISTENT); 189 } 190 191 if ((pMechanism->pParameter == NULL) || 192 (pMechanism->ulParameterLen != AES_BLOCK_LEN)) { 193 return (CKR_MECHANISM_PARAM_INVALID); 194 } 195 196 rv = soft_aes_crypt_init_common(session_p, pMechanism, 197 key_p, B_FALSE); 198 199 if (rv != CKR_OK) 200 return (rv); 201 202 (void) pthread_mutex_lock(&session_p->session_mutex); 203 204 soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context; 205 206 /* Save Initialization Vector (IV) in the context. */ 207 (void) memcpy(soft_aes_ctx->ivec, pMechanism->pParameter, 208 AES_BLOCK_LEN); 209 210 /* Allocate a context for AES cipher-block chaining. */ 211 soft_aes_ctx->aes_cbc = (void *)aes_cbc_ctx_init( 212 soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len, 213 soft_aes_ctx->ivec); 214 215 if (soft_aes_ctx->aes_cbc == NULL) { 216 bzero(soft_aes_ctx->key_sched, 217 soft_aes_ctx->keysched_len); 218 free(soft_aes_ctx->key_sched); 219 free(session_p->decrypt.context); 220 session_p->decrypt.context = NULL; 221 (void) pthread_mutex_unlock(&session_p->session_mutex); 222 return (CKR_HOST_MEMORY); 223 } 224 225 (void) pthread_mutex_unlock(&session_p->session_mutex); 226 227 return (rv); 228 } 229 230 case CKM_RC4: 231 232 if (key_p->key_type != CKK_RC4) { 233 return (CKR_KEY_TYPE_INCONSISTENT); 234 } 235 236 return (soft_arcfour_crypt_init(session_p, pMechanism, key_p, 237 B_FALSE)); 238 239 case CKM_RSA_X_509: 240 case CKM_RSA_PKCS: 241 242 if (key_p->key_type != CKK_RSA) { 243 return (CKR_KEY_TYPE_INCONSISTENT); 244 } 245 246 return (soft_rsa_crypt_init_common(session_p, pMechanism, 247 key_p, B_FALSE)); 248 249 default: 250 return (CKR_MECHANISM_INVALID); 251 } 252 } 253 254 255 /* 256 * soft_decrypt_common() 257 * 258 * Arguments: 259 * session_p: pointer to soft_session_t struct 260 * pEncrypted: pointer to the encrypted data as input 261 * ulEncryptedLen: length of the input data 262 * pData: pointer to the output data contains plaintext 263 * pulDataLen: pointer to the length of the output data 264 * Update: boolean flag indicates caller is soft_decrypt 265 * or soft_decrypt_update 266 * 267 * Description: 268 * This function calls the corresponding decrypt routine based 269 * on the mechanism. 270 * 271 * Returns: 272 * see soft_decrypt_common(). 273 */ 274 CK_RV 275 soft_decrypt_common(soft_session_t *session_p, CK_BYTE_PTR pEncrypted, 276 CK_ULONG ulEncryptedLen, CK_BYTE_PTR pData, 277 CK_ULONG_PTR pulDataLen, boolean_t Update) 278 { 279 280 CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism; 281 282 switch (mechanism) { 283 284 case CKM_DES_ECB: 285 case CKM_DES_CBC: 286 case CKM_DES_CBC_PAD: 287 case CKM_DES3_ECB: 288 case CKM_DES3_CBC: 289 case CKM_DES3_CBC_PAD: 290 291 return (soft_des_decrypt_common(session_p, pEncrypted, 292 ulEncryptedLen, pData, pulDataLen, Update)); 293 294 case CKM_AES_ECB: 295 case CKM_AES_CBC: 296 case CKM_AES_CBC_PAD: 297 298 return (soft_aes_decrypt_common(session_p, pEncrypted, 299 ulEncryptedLen, pData, pulDataLen, Update)); 300 301 case CKM_RC4: 302 { 303 ARCFour_key *keystream = session_p->decrypt.context; 304 CK_RV rv; 305 306 rv = soft_arcfour_crypt(&(session_p->decrypt), pEncrypted, 307 ulEncryptedLen, pData, pulDataLen); 308 309 if ((rv == CKR_OK) && (pData != NULL)) { 310 bzero(keystream, sizeof (*keystream)); 311 free(keystream); 312 session_p->decrypt.context = NULL; 313 } 314 return (rv); 315 } 316 317 case CKM_RSA_X_509: 318 case CKM_RSA_PKCS: 319 320 return (soft_rsa_decrypt_common(session_p, pEncrypted, 321 ulEncryptedLen, pData, pulDataLen, mechanism)); 322 323 default: 324 return (CKR_MECHANISM_INVALID); 325 326 } 327 } 328 329 330 /* 331 * soft_decrypt() 332 * 333 * Arguments: 334 * session_p: pointer to soft_session_t struct 335 * pEncryptedData: pointer to the encrypted data as input 336 * ulEncryptedDataLen: length of the input data 337 * pData: pointer to the output data contains plaintext 338 * pulDataLen: pointer to the length of the output data 339 * 340 * Description: 341 * called by C_Decrypt(). This function calls the soft_decrypt_common 342 * routine. 343 * 344 * Returns: 345 * see soft_decrypt_common(). 346 */ 347 CK_RV 348 soft_decrypt(soft_session_t *session_p, CK_BYTE_PTR pEncryptedData, 349 CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, 350 CK_ULONG_PTR pulDataLen) 351 { 352 353 return (soft_decrypt_common(session_p, pEncryptedData, 354 ulEncryptedDataLen, pData, pulDataLen, B_FALSE)); 355 } 356 357 358 /* 359 * soft_decrypt_update() 360 * 361 * Arguments: 362 * session_p: pointer to soft_session_t struct 363 * pEncryptedPart: pointer to the encrypted data as input 364 * ulEncryptedPartLen: length of the input data 365 * pPart: pointer to the output data contains plaintext 366 * pulPartLen: pointer to the length of the output data 367 * 368 * Description: 369 * called by C_DecryptUpdate(). This function calls the 370 * soft_decrypt_common routine (with update flag on). 371 * 372 * Returns: 373 * see soft_decrypt_common(). 374 */ 375 CK_RV 376 soft_decrypt_update(soft_session_t *session_p, CK_BYTE_PTR pEncryptedPart, 377 CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, 378 CK_ULONG_PTR pulPartLen) 379 { 380 381 CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism; 382 383 switch (mechanism) { 384 385 case CKM_DES_ECB: 386 case CKM_DES_CBC: 387 case CKM_DES_CBC_PAD: 388 case CKM_DES3_ECB: 389 case CKM_DES3_CBC: 390 case CKM_DES3_CBC_PAD: 391 case CKM_AES_ECB: 392 case CKM_AES_CBC: 393 case CKM_AES_CBC_PAD: 394 395 return (soft_decrypt_common(session_p, pEncryptedPart, 396 ulEncryptedPartLen, pPart, pulPartLen, B_TRUE)); 397 398 case CKM_RC4: 399 400 return (soft_arcfour_crypt(&(session_p->decrypt), 401 pEncryptedPart, ulEncryptedPartLen, pPart, pulPartLen)); 402 403 default: 404 /* PKCS11: The mechanism only supports single-part operation. */ 405 return (CKR_MECHANISM_INVALID); 406 } 407 408 } 409 410 411 /* 412 * soft_decrypt_final() 413 * 414 * Arguments: 415 * session_p: pointer to soft_session_t struct 416 * pLastPart: pointer to the last recovered data part 417 * pulLastPartLen: pointer to the length of the last recovered data part 418 * 419 * Description: 420 * called by C_DecryptFinal(). 421 * 422 * Returns: 423 * CKR_OK: success 424 * CKR_FUNCTION_FAILED: decrypt final function failed 425 * CKR_ENCRYPTED_DATA_LEN_RANGE: remaining buffer contains bad length 426 */ 427 CK_RV 428 soft_decrypt_final(soft_session_t *session_p, CK_BYTE_PTR pLastPart, 429 CK_ULONG_PTR pulLastPartLen) 430 { 431 432 CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism; 433 CK_ULONG out_len; 434 CK_RV rv = CKR_OK; 435 int rc; 436 437 (void) pthread_mutex_lock(&session_p->session_mutex); 438 439 if (session_p->decrypt.context == NULL) { 440 rv = CKR_OPERATION_NOT_INITIALIZED; 441 *pulLastPartLen = 0; 442 goto clean2; 443 } 444 switch (mechanism) { 445 446 case CKM_DES_CBC_PAD: 447 case CKM_DES3_CBC_PAD: 448 { 449 450 soft_des_ctx_t *soft_des_ctx; 451 452 soft_des_ctx = (soft_des_ctx_t *)session_p->decrypt.context; 453 454 /* 455 * We should have only one block of data left in the 456 * remaining buffer. 457 */ 458 if (soft_des_ctx->remain_len != DES_BLOCK_LEN) { 459 *pulLastPartLen = 0; 460 rv = CKR_ENCRYPTED_DATA_LEN_RANGE; 461 /* Cleanup memory space. */ 462 free(soft_des_ctx->des_cbc); 463 bzero(soft_des_ctx->key_sched, 464 soft_des_ctx->keysched_len); 465 free(soft_des_ctx->key_sched); 466 467 goto clean1; 468 } 469 470 out_len = DES_BLOCK_LEN; 471 472 /* 473 * If application asks for the length of the output buffer 474 * to hold the plaintext? 475 */ 476 if (pLastPart == NULL) { 477 *pulLastPartLen = out_len; 478 rv = CKR_OK; 479 goto clean2; 480 } else { 481 crypto_data_t out; 482 483 /* Copy remaining data to the output buffer. */ 484 (void) memcpy(pLastPart, soft_des_ctx->data, 485 DES_BLOCK_LEN); 486 487 out.cd_format = CRYPTO_DATA_RAW; 488 out.cd_offset = 0; 489 out.cd_length = DES_BLOCK_LEN; 490 out.cd_raw.iov_base = (char *)pLastPart; 491 out.cd_raw.iov_len = DES_BLOCK_LEN; 492 493 /* Decrypt final block of data. */ 494 rc = des_decrypt_contiguous_blocks( 495 (des_ctx_t *)soft_des_ctx->des_cbc, 496 (char *)pLastPart, DES_BLOCK_LEN, &out); 497 498 if (rc == 0) { 499 /* 500 * Remove padding bytes after decryption of 501 * ciphertext block to produce the original 502 * plaintext. 503 */ 504 rv = soft_remove_pkcs7_padding(pLastPart, 505 DES_BLOCK_LEN, &out_len, DES_BLOCK_LEN); 506 if (rv != CKR_OK) 507 *pulLastPartLen = 0; 508 else 509 *pulLastPartLen = out_len; 510 } else { 511 *pulLastPartLen = 0; 512 rv = CKR_FUNCTION_FAILED; 513 } 514 515 /* Cleanup memory space. */ 516 free(soft_des_ctx->des_cbc); 517 bzero(soft_des_ctx->key_sched, 518 soft_des_ctx->keysched_len); 519 free(soft_des_ctx->key_sched); 520 521 } 522 523 break; 524 } 525 526 case CKM_DES_CBC: 527 case CKM_DES_ECB: 528 case CKM_DES3_CBC: 529 case CKM_DES3_ECB: 530 { 531 532 soft_des_ctx_t *soft_des_ctx; 533 534 soft_des_ctx = (soft_des_ctx_t *)session_p->decrypt.context; 535 /* 536 * CKM_DES_CBC and CKM_DES_ECB does not do any padding, 537 * so when the final is called, the remaining buffer 538 * should not contain any more data. 539 */ 540 *pulLastPartLen = 0; 541 if (soft_des_ctx->remain_len != 0) { 542 rv = CKR_ENCRYPTED_DATA_LEN_RANGE; 543 } else { 544 if (pLastPart == NULL) 545 goto clean2; 546 } 547 548 /* Cleanup memory space. */ 549 free(soft_des_ctx->des_cbc); 550 bzero(soft_des_ctx->key_sched, soft_des_ctx->keysched_len); 551 free(soft_des_ctx->key_sched); 552 553 break; 554 } 555 556 case CKM_AES_CBC_PAD: 557 { 558 559 soft_aes_ctx_t *soft_aes_ctx; 560 561 soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context; 562 563 /* 564 * We should have only one block of data left in the 565 * remaining buffer. 566 */ 567 if (soft_aes_ctx->remain_len != AES_BLOCK_LEN) { 568 *pulLastPartLen = 0; 569 rv = CKR_ENCRYPTED_DATA_LEN_RANGE; 570 /* Cleanup memory space. */ 571 free(soft_aes_ctx->aes_cbc); 572 bzero(soft_aes_ctx->key_sched, 573 soft_aes_ctx->keysched_len); 574 free(soft_aes_ctx->key_sched); 575 576 goto clean1; 577 } 578 579 out_len = AES_BLOCK_LEN; 580 581 /* 582 * If application asks for the length of the output buffer 583 * to hold the plaintext? 584 */ 585 if (pLastPart == NULL) { 586 *pulLastPartLen = out_len; 587 rv = CKR_OK; 588 goto clean2; 589 } else { 590 crypto_data_t out; 591 592 /* Copy remaining data to the output buffer. */ 593 (void) memcpy(pLastPart, soft_aes_ctx->data, 594 AES_BLOCK_LEN); 595 596 out.cd_format = CRYPTO_DATA_RAW; 597 out.cd_offset = 0; 598 out.cd_length = AES_BLOCK_LEN; 599 out.cd_raw.iov_base = (char *)pLastPart; 600 out.cd_raw.iov_len = AES_BLOCK_LEN; 601 602 /* Decrypt final block of data. */ 603 rc = aes_decrypt_contiguous_blocks( 604 (aes_ctx_t *)soft_aes_ctx->aes_cbc, 605 (char *)pLastPart, AES_BLOCK_LEN, &out); 606 607 if (rc == 0) { 608 /* 609 * Remove padding bytes after decryption of 610 * ciphertext block to produce the original 611 * plaintext. 612 */ 613 rv = soft_remove_pkcs7_padding(pLastPart, 614 AES_BLOCK_LEN, &out_len, AES_BLOCK_LEN); 615 if (rv != CKR_OK) 616 *pulLastPartLen = 0; 617 else 618 *pulLastPartLen = out_len; 619 } else { 620 *pulLastPartLen = 0; 621 rv = CKR_FUNCTION_FAILED; 622 } 623 624 /* Cleanup memory space. */ 625 free(soft_aes_ctx->aes_cbc); 626 bzero(soft_aes_ctx->key_sched, 627 soft_aes_ctx->keysched_len); 628 free(soft_aes_ctx->key_sched); 629 630 } 631 632 break; 633 } 634 635 case CKM_AES_CBC: 636 case CKM_AES_ECB: 637 { 638 soft_aes_ctx_t *soft_aes_ctx; 639 640 soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context; 641 /* 642 * CKM_AES_CBC and CKM_AES_ECB does not do any padding, 643 * so when the final is called, the remaining buffer 644 * should not contain any more data. 645 */ 646 *pulLastPartLen = 0; 647 if (soft_aes_ctx->remain_len != 0) { 648 rv = CKR_ENCRYPTED_DATA_LEN_RANGE; 649 } else { 650 if (pLastPart == NULL) 651 goto clean2; 652 } 653 654 /* Cleanup memory space. */ 655 free(soft_aes_ctx->aes_cbc); 656 bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len); 657 free(soft_aes_ctx->key_sched); 658 659 break; 660 } 661 662 case CKM_RC4: 663 { 664 ARCFour_key *key = (ARCFour_key *)session_p->decrypt.context; 665 bzero(key, sizeof (*key)); 666 *pulLastPartLen = 0; 667 break; 668 } 669 670 default: 671 /* PKCS11: The mechanism only supports single-part operation. */ 672 rv = CKR_MECHANISM_INVALID; 673 break; 674 } 675 676 clean1: 677 free(session_p->decrypt.context); 678 session_p->decrypt.context = NULL; 679 680 clean2: 681 (void) pthread_mutex_unlock(&session_p->session_mutex); 682 683 return (rv); 684 685 } 686