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 /*
  23  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  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 <arcfour.h>
  34 #include "softSession.h"
  35 #include "softObject.h"
  36 #include "softOps.h"
  37 #include "softCrypt.h"
  38 #include "softRSA.h"
  39 
  40 /*
  41  * Remove padding bytes.
  42  */
  43 CK_RV
  44 soft_remove_pkcs7_padding(CK_BYTE *pData, CK_ULONG padded_len,
  45     CK_ULONG *pulDataLen)
  46 {
  47         CK_RV   rv;
  48 
  49 #ifdef  __sparcv9
  50         if ((rv = pkcs7_decode(pData, (&padded_len))) != CKR_OK)
  51 #else   /* !__sparcv9 */
  52         if ((rv = pkcs7_decode(pData, (size_t *)(&padded_len))) != CKR_OK)
  53 #endif  /* __sparcv9 */
  54                 return (rv);
  55 
  56         *pulDataLen = padded_len;
  57         return (CKR_OK);
  58 }
  59 
  60 
  61 /*
  62  * soft_decrypt_init()
  63  *
  64  * Arguments:
  65  *      session_p:      pointer to soft_session_t struct
  66  *      pMechanism:     pointer to CK_MECHANISM struct provided by application
  67  *      key_p:          pointer to key soft_object_t struct
  68  *
  69  * Description:
  70  *      called by C_DecryptInit(). This function calls the corresponding
  71  *      decrypt init routine based on the mechanism.
  72  *
  73  * Returns:
  74  *      CKR_OK: success
  75  *      CKR_HOST_MEMORY: run out of system memory
  76  *      CKR_MECHANISM_PARAM_INVALID: invalid parameters in mechanism
  77  *      CKR_MECHANISM_INVALID: invalid mechanism type
  78  *      CKR_KEY_TYPE_INCONSISTENT: incorrect type of key to use
  79  *                                 with the specified mechanism
  80  */
  81 CK_RV
  82 soft_decrypt_init(soft_session_t *session_p, CK_MECHANISM_PTR pMechanism,
  83     soft_object_t *key_p)
  84 {
  85 
  86         CK_RV rv;
  87 
  88         switch (pMechanism->mechanism) {
  89 
  90         case CKM_DES_ECB:
  91 
  92                 if (key_p->key_type != CKK_DES) {
  93                         return (CKR_KEY_TYPE_INCONSISTENT);
  94                 }
  95 
  96                 goto ecb_common;
  97 
  98         case CKM_DES3_ECB:
  99 
 100                 if ((key_p->key_type != CKK_DES2) &&
 101                     (key_p->key_type != CKK_DES3)) {
 102                         return (CKR_KEY_TYPE_INCONSISTENT);
 103                 }
 104 
 105 ecb_common:
 106 
 107                 return (soft_des_crypt_init_common(session_p, pMechanism,
 108                     key_p, B_FALSE));
 109 
 110         case CKM_DES_CBC:
 111         case CKM_DES_CBC_PAD:
 112 
 113                 if (key_p->key_type != CKK_DES) {
 114                         return (CKR_KEY_TYPE_INCONSISTENT);
 115                 }
 116 
 117                 goto cbc_common;
 118 
 119         case CKM_DES3_CBC:
 120         case CKM_DES3_CBC_PAD:
 121         {
 122                 soft_des_ctx_t *soft_des_ctx;
 123 
 124                 if ((key_p->key_type != CKK_DES2) &&
 125                     (key_p->key_type != CKK_DES3)) {
 126                         return (CKR_KEY_TYPE_INCONSISTENT);
 127                 }
 128 
 129 cbc_common:
 130                 if ((pMechanism->pParameter == NULL) ||
 131                     (pMechanism->ulParameterLen != DES_BLOCK_LEN)) {
 132                         return (CKR_MECHANISM_PARAM_INVALID);
 133                 }
 134 
 135                 rv = soft_des_crypt_init_common(session_p, pMechanism,
 136                     key_p, B_FALSE);
 137 
 138                 if (rv != CKR_OK)
 139                         return (rv);
 140 
 141                 (void) pthread_mutex_lock(&session_p->session_mutex);
 142 
 143                 soft_des_ctx = (soft_des_ctx_t *)session_p->decrypt.context;
 144                 /* Save Initialization Vector (IV) in the context. */
 145                 (void) memcpy(soft_des_ctx->ivec, pMechanism->pParameter,
 146                     DES_BLOCK_LEN);
 147 
 148                 /* Allocate a context for DES cipher-block chaining. */
 149                 soft_des_ctx->des_cbc = (void *)des_cbc_ctx_init(
 150                     soft_des_ctx->key_sched, soft_des_ctx->keysched_len,
 151                     soft_des_ctx->ivec, key_p->key_type);
 152 
 153                 if (soft_des_ctx->des_cbc == NULL) {
 154                         bzero(soft_des_ctx->key_sched,
 155                             soft_des_ctx->keysched_len);
 156                         free(soft_des_ctx->key_sched);
 157                         free(session_p->decrypt.context);
 158                         session_p->decrypt.context = NULL;
 159                         (void) pthread_mutex_unlock(&session_p->session_mutex);
 160                         return (CKR_HOST_MEMORY);
 161                 }
 162 
 163                 (void) pthread_mutex_unlock(&session_p->session_mutex);
 164 
 165                 return (rv);
 166         }
 167         case CKM_AES_ECB:
 168 
 169                 if (key_p->key_type != CKK_AES) {
 170                         return (CKR_KEY_TYPE_INCONSISTENT);
 171                 }
 172 
 173                 return (soft_aes_crypt_init_common(session_p, pMechanism,
 174                     key_p, B_FALSE));
 175 
 176         case CKM_AES_CBC:
 177         case CKM_AES_CBC_PAD:
 178         {
 179                 soft_aes_ctx_t *soft_aes_ctx;
 180 
 181                 if (key_p->key_type != CKK_AES) {
 182                         return (CKR_KEY_TYPE_INCONSISTENT);
 183                 }
 184 
 185                 if ((pMechanism->pParameter == NULL) ||
 186                     (pMechanism->ulParameterLen != AES_BLOCK_LEN)) {
 187                         return (CKR_MECHANISM_PARAM_INVALID);
 188                 }
 189 
 190                 rv = soft_aes_crypt_init_common(session_p, pMechanism,
 191                     key_p, B_FALSE);
 192 
 193                 if (rv != CKR_OK)
 194                         return (rv);
 195 
 196                 (void) pthread_mutex_lock(&session_p->session_mutex);
 197 
 198                 soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
 199 
 200                 /* Save Initialization Vector (IV) in the context. */
 201                 (void) memcpy(soft_aes_ctx->ivec, pMechanism->pParameter,
 202                     AES_BLOCK_LEN);
 203 
 204                 /* Allocate a context for AES cipher-block chaining. */
 205                 soft_aes_ctx->aes_cbc = (void *)aes_cbc_ctx_init(
 206                     soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len,
 207                     soft_aes_ctx->ivec);
 208 
 209                 if (soft_aes_ctx->aes_cbc == NULL) {
 210                         bzero(soft_aes_ctx->key_sched,
 211                             soft_aes_ctx->keysched_len);
 212                         free(soft_aes_ctx->key_sched);
 213                         free(session_p->decrypt.context);
 214                         session_p->decrypt.context = NULL;
 215                         (void) pthread_mutex_unlock(&session_p->session_mutex);
 216                         return (CKR_HOST_MEMORY);
 217                 }
 218 
 219                 (void) pthread_mutex_unlock(&session_p->session_mutex);
 220 
 221                 return (rv);
 222         }
 223         case CKM_AES_CTR:
 224         {
 225                 soft_aes_ctx_t *soft_aes_ctx;
 226 
 227                 if (key_p->key_type != CKK_AES) {
 228                         return (CKR_KEY_TYPE_INCONSISTENT);
 229                 }
 230 
 231                 if (pMechanism->pParameter == NULL ||
 232                     pMechanism->ulParameterLen != sizeof (CK_AES_CTR_PARAMS)) {
 233                         return (CKR_MECHANISM_PARAM_INVALID);
 234                 }
 235 
 236                 rv = soft_aes_crypt_init_common(session_p, pMechanism,
 237                     key_p, B_FALSE);
 238 
 239                 if (rv != CKR_OK)
 240                         return (rv);
 241 
 242                 (void) pthread_mutex_lock(&session_p->session_mutex);
 243 
 244                 soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
 245                 soft_aes_ctx->aes_cbc = aes_ctr_ctx_init(
 246                     soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len,
 247                     pMechanism->pParameter);
 248 
 249                 if (soft_aes_ctx->aes_cbc == NULL) {
 250                         bzero(soft_aes_ctx->key_sched,
 251                             soft_aes_ctx->keysched_len);
 252                         free(soft_aes_ctx->key_sched);
 253                         free(session_p->decrypt.context);
 254                         session_p->decrypt.context = NULL;
 255                         rv = CKR_HOST_MEMORY;
 256                 }
 257 
 258                 (void) pthread_mutex_unlock(&session_p->session_mutex);
 259 
 260                 return (rv);
 261         }
 262         case CKM_BLOWFISH_CBC:
 263         {
 264                 soft_blowfish_ctx_t *soft_blowfish_ctx;
 265 
 266                 if (key_p->key_type != CKK_BLOWFISH)
 267                         return (CKR_KEY_TYPE_INCONSISTENT);
 268 
 269                 if ((pMechanism->pParameter == NULL) ||
 270                     (pMechanism->ulParameterLen != BLOWFISH_BLOCK_LEN))
 271                         return (CKR_MECHANISM_PARAM_INVALID);
 272 
 273                 rv = soft_blowfish_crypt_init_common(session_p, pMechanism,
 274                     key_p, B_FALSE);
 275 
 276                 if (rv != CKR_OK)
 277                         return (rv);
 278 
 279                 (void) pthread_mutex_lock(&session_p->session_mutex);
 280 
 281                 soft_blowfish_ctx =
 282                     (soft_blowfish_ctx_t *)session_p->decrypt.context;
 283 
 284                 /* Save Initialization Vector in the context. */
 285                 (void) memcpy(soft_blowfish_ctx->ivec, pMechanism->pParameter,
 286                     BLOWFISH_BLOCK_LEN);
 287 
 288                 /* Allocate a context for CBC */
 289                 soft_blowfish_ctx->blowfish_cbc =
 290                     (void *)blowfish_cbc_ctx_init(soft_blowfish_ctx->key_sched,
 291                     soft_blowfish_ctx->keysched_len,
 292                     soft_blowfish_ctx->ivec);
 293 
 294                 if (soft_blowfish_ctx->blowfish_cbc == NULL) {
 295                         bzero(soft_blowfish_ctx->key_sched,
 296                             soft_blowfish_ctx->keysched_len);
 297                         free(soft_blowfish_ctx->key_sched);
 298                         free(session_p->decrypt.context = NULL);
 299                         (void) pthread_mutex_unlock(&session_p->session_mutex);
 300                         return (CKR_HOST_MEMORY);
 301                 }
 302 
 303                 (void) pthread_mutex_unlock(&session_p->session_mutex);
 304                 return (rv);
 305         }
 306 
 307         case CKM_RC4:
 308 
 309                 if (key_p->key_type != CKK_RC4) {
 310                         return (CKR_KEY_TYPE_INCONSISTENT);
 311                 }
 312 
 313                 return (soft_arcfour_crypt_init(session_p, pMechanism, key_p,
 314                     B_FALSE));
 315 
 316         case CKM_RSA_X_509:
 317         case CKM_RSA_PKCS:
 318 
 319                 if (key_p->key_type != CKK_RSA) {
 320                         return (CKR_KEY_TYPE_INCONSISTENT);
 321                 }
 322 
 323                 return (soft_rsa_crypt_init_common(session_p, pMechanism,
 324                     key_p, B_FALSE));
 325 
 326         default:
 327                 return (CKR_MECHANISM_INVALID);
 328         }
 329 }
 330 
 331 
 332 /*
 333  * soft_decrypt_common()
 334  *
 335  * Arguments:
 336  *      session_p:      pointer to soft_session_t struct
 337  *      pEncrypted:     pointer to the encrypted data as input
 338  *      ulEncryptedLen: length of the input data
 339  *      pData:          pointer to the output data contains plaintext
 340  *      pulDataLen:     pointer to the length of the output data
 341  *      Update:         boolean flag indicates caller is soft_decrypt
 342  *                      or soft_decrypt_update
 343  *
 344  * Description:
 345  *      This function calls the corresponding decrypt routine based
 346  *      on the mechanism.
 347  *
 348  * Returns:
 349  *      see soft_decrypt_common().
 350  */
 351 CK_RV
 352 soft_decrypt_common(soft_session_t *session_p, CK_BYTE_PTR pEncrypted,
 353     CK_ULONG ulEncryptedLen, CK_BYTE_PTR pData,
 354     CK_ULONG_PTR pulDataLen, boolean_t Update)
 355 {
 356 
 357         CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
 358 
 359         switch (mechanism) {
 360 
 361         case CKM_DES_ECB:
 362         case CKM_DES_CBC:
 363         case CKM_DES3_ECB:
 364         case CKM_DES3_CBC:
 365 
 366                 if (ulEncryptedLen == 0) {
 367                         *pulDataLen = 0;
 368                         return (CKR_OK);
 369                 }
 370                 /* FALLTHROUGH */
 371 
 372         case CKM_DES_CBC_PAD:
 373         case CKM_DES3_CBC_PAD:
 374 
 375                 return (soft_des_decrypt_common(session_p, pEncrypted,
 376                     ulEncryptedLen, pData, pulDataLen, Update));
 377 
 378         case CKM_AES_ECB:
 379         case CKM_AES_CBC:
 380         case CKM_AES_CTR:
 381 
 382                 if (ulEncryptedLen == 0) {
 383                         *pulDataLen = 0;
 384                         return (CKR_OK);
 385                 }
 386                 /* FALLTHROUGH */
 387 
 388         case CKM_AES_CBC_PAD:
 389 
 390                 return (soft_aes_decrypt_common(session_p, pEncrypted,
 391                     ulEncryptedLen, pData, pulDataLen, Update));
 392 
 393         case CKM_BLOWFISH_CBC:
 394 
 395                 if (ulEncryptedLen == 0) {
 396                         *pulDataLen = 0;
 397                         return (CKR_OK);
 398                 }
 399 
 400                 return (soft_blowfish_decrypt_common(session_p, pEncrypted,
 401                     ulEncryptedLen, pData, pulDataLen, Update));
 402 
 403         case CKM_RC4:
 404 
 405                 if (ulEncryptedLen == 0) {
 406                         *pulDataLen = 0;
 407                         return (CKR_OK);
 408                 }
 409 
 410 
 411                 return (soft_arcfour_crypt(&(session_p->decrypt), pEncrypted,
 412                     ulEncryptedLen, pData, pulDataLen));
 413 
 414         case CKM_RSA_X_509:
 415         case CKM_RSA_PKCS:
 416 
 417                 return (soft_rsa_decrypt_common(session_p, pEncrypted,
 418                     ulEncryptedLen, pData, pulDataLen, mechanism));
 419 
 420         default:
 421                 return (CKR_MECHANISM_INVALID);
 422 
 423         }
 424 }
 425 
 426 
 427 /*
 428  * soft_decrypt()
 429  *
 430  * Arguments:
 431  *      session_p:      pointer to soft_session_t struct
 432  *      pEncryptedData: pointer to the encrypted data as input
 433  *      ulEncryptedDataLen: length of the input data
 434  *      pData:          pointer to the output data contains plaintext
 435  *      pulDataLen:     pointer to the length of the output data
 436  *
 437  * Description:
 438  *      called by C_Decrypt(). This function calls the soft_decrypt_common
 439  *      routine.
 440  *
 441  * Returns:
 442  *      see soft_decrypt_common().
 443  */
 444 CK_RV
 445 soft_decrypt(soft_session_t *session_p, CK_BYTE_PTR pEncryptedData,
 446     CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData,
 447     CK_ULONG_PTR pulDataLen)
 448 {
 449 
 450         return (soft_decrypt_common(session_p, pEncryptedData,
 451             ulEncryptedDataLen, pData, pulDataLen, B_FALSE));
 452 }
 453 
 454 
 455 /*
 456  * soft_decrypt_update()
 457  *
 458  * Arguments:
 459  *      session_p:      pointer to soft_session_t struct
 460  *      pEncryptedPart: pointer to the encrypted data as input
 461  *      ulEncryptedPartLen: length of the input data
 462  *      pPart:          pointer to the output data contains plaintext
 463  *      pulPartLen:     pointer to the length of the output data
 464  *
 465  * Description:
 466  *      called by C_DecryptUpdate(). This function calls the
 467  *      soft_decrypt_common routine (with update flag on).
 468  *
 469  * Returns:
 470  *      see soft_decrypt_common().
 471  */
 472 CK_RV
 473 soft_decrypt_update(soft_session_t *session_p, CK_BYTE_PTR pEncryptedPart,
 474         CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart,
 475         CK_ULONG_PTR pulPartLen)
 476 {
 477         CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
 478 
 479         switch (mechanism) {
 480 
 481         case CKM_DES_ECB:
 482         case CKM_DES_CBC:
 483         case CKM_DES_CBC_PAD:
 484         case CKM_DES3_ECB:
 485         case CKM_DES3_CBC:
 486         case CKM_DES3_CBC_PAD:
 487         case CKM_AES_ECB:
 488         case CKM_AES_CBC:
 489         case CKM_AES_CBC_PAD:
 490         case CKM_AES_CTR:
 491         case CKM_BLOWFISH_CBC:
 492         case CKM_RC4:
 493 
 494                 return (soft_decrypt_common(session_p, pEncryptedPart,
 495                     ulEncryptedPartLen, pPart, pulPartLen, B_TRUE));
 496 
 497         default:
 498                 /* PKCS11: The mechanism only supports single-part operation. */
 499                 return (CKR_MECHANISM_INVALID);
 500         }
 501 
 502 }
 503 
 504 
 505 /*
 506  * soft_decrypt_final()
 507  *
 508  * Arguments:
 509  *      session_p:      pointer to soft_session_t struct
 510  *      pLastPart:      pointer to the last recovered data part
 511  *      pulLastPartLen: pointer to the length of the last recovered data part
 512  *
 513  * Description:
 514  *      called by C_DecryptFinal().
 515  *
 516  * Returns:
 517  *      CKR_OK: success
 518  *      CKR_FUNCTION_FAILED: decrypt final function failed
 519  *      CKR_ENCRYPTED_DATA_LEN_RANGE: remaining buffer contains bad length
 520  */
 521 CK_RV
 522 soft_decrypt_final(soft_session_t *session_p, CK_BYTE_PTR pLastPart,
 523         CK_ULONG_PTR pulLastPartLen)
 524 {
 525 
 526         CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
 527         CK_ULONG out_len;
 528         CK_RV rv = CKR_OK;
 529         int rc;
 530 
 531         (void) pthread_mutex_lock(&session_p->session_mutex);
 532 
 533         if (session_p->decrypt.context == NULL) {
 534                 rv = CKR_OPERATION_NOT_INITIALIZED;
 535                 *pulLastPartLen = 0;
 536                 goto clean2;
 537         }
 538         switch (mechanism) {
 539 
 540         case CKM_DES_CBC_PAD:
 541         case CKM_DES3_CBC_PAD:
 542         {
 543 
 544                 soft_des_ctx_t *soft_des_ctx;
 545 
 546                 soft_des_ctx = (soft_des_ctx_t *)session_p->decrypt.context;
 547 
 548                 /*
 549                  * We should have only one block of data left in the
 550                  * remaining buffer.
 551                  */
 552                 if (soft_des_ctx->remain_len != DES_BLOCK_LEN) {
 553                         *pulLastPartLen = 0;
 554                         rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
 555                         /* Cleanup memory space. */
 556                         free(soft_des_ctx->des_cbc);
 557                         bzero(soft_des_ctx->key_sched,
 558                             soft_des_ctx->keysched_len);
 559                         free(soft_des_ctx->key_sched);
 560 
 561                         goto clean1;
 562                 }
 563 
 564                 out_len = DES_BLOCK_LEN;
 565 
 566                 /*
 567                  * If application asks for the length of the output buffer
 568                  * to hold the plaintext?
 569                  */
 570                 if (pLastPart == NULL) {
 571                         *pulLastPartLen = out_len;
 572                         rv = CKR_OK;
 573                         goto clean2;
 574                 } else {
 575                         crypto_data_t out;
 576 
 577                         /* Copy remaining data to the output buffer. */
 578                         (void) memcpy(pLastPart, soft_des_ctx->data,
 579                             DES_BLOCK_LEN);
 580 
 581                         out.cd_format = CRYPTO_DATA_RAW;
 582                         out.cd_offset = 0;
 583                         out.cd_length = DES_BLOCK_LEN;
 584                         out.cd_raw.iov_base = (char *)pLastPart;
 585                         out.cd_raw.iov_len = DES_BLOCK_LEN;
 586 
 587                         /* Decrypt final block of data. */
 588                         rc = des_decrypt_contiguous_blocks(
 589                             (des_ctx_t *)soft_des_ctx->des_cbc,
 590                             (char *)pLastPart, DES_BLOCK_LEN, &out);
 591 
 592                         if (rc == 0) {
 593                                 /*
 594                                  * Remove padding bytes after decryption of
 595                                  * ciphertext block to produce the original
 596                                  * plaintext.
 597                                  */
 598                                 rv = soft_remove_pkcs7_padding(pLastPart,
 599                                     DES_BLOCK_LEN, &out_len);
 600                                 if (rv != CKR_OK)
 601                                         *pulLastPartLen = 0;
 602                                 else
 603                                         *pulLastPartLen = out_len;
 604                         } else {
 605                                 *pulLastPartLen = 0;
 606                                 rv = CKR_FUNCTION_FAILED;
 607                         }
 608 
 609                         /* Cleanup memory space. */
 610                         free(soft_des_ctx->des_cbc);
 611                         bzero(soft_des_ctx->key_sched,
 612                             soft_des_ctx->keysched_len);
 613                         free(soft_des_ctx->key_sched);
 614 
 615                 }
 616 
 617                 break;
 618         }
 619 
 620         case CKM_DES_CBC:
 621         case CKM_DES_ECB:
 622         case CKM_DES3_CBC:
 623         case CKM_DES3_ECB:
 624         {
 625 
 626                 soft_des_ctx_t *soft_des_ctx;
 627 
 628                 soft_des_ctx = (soft_des_ctx_t *)session_p->decrypt.context;
 629                 /*
 630                  * CKM_DES_CBC and CKM_DES_ECB does not do any padding,
 631                  * so when the final is called, the remaining buffer
 632                  * should not contain any more data.
 633                  */
 634                 *pulLastPartLen = 0;
 635                 if (soft_des_ctx->remain_len != 0) {
 636                         rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
 637                 } else {
 638                         if (pLastPart == NULL)
 639                                 goto clean2;
 640                 }
 641 
 642                 /* Cleanup memory space. */
 643                 free(soft_des_ctx->des_cbc);
 644                 bzero(soft_des_ctx->key_sched, soft_des_ctx->keysched_len);
 645                 free(soft_des_ctx->key_sched);
 646 
 647                 break;
 648         }
 649 
 650         case CKM_AES_CBC_PAD:
 651         {
 652 
 653                 soft_aes_ctx_t *soft_aes_ctx;
 654 
 655                 soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
 656 
 657                 /*
 658                  * We should have only one block of data left in the
 659                  * remaining buffer.
 660                  */
 661                 if (soft_aes_ctx->remain_len != AES_BLOCK_LEN) {
 662                         *pulLastPartLen = 0;
 663                         rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
 664                         /* Cleanup memory space. */
 665                         free(soft_aes_ctx->aes_cbc);
 666                         bzero(soft_aes_ctx->key_sched,
 667                             soft_aes_ctx->keysched_len);
 668                         free(soft_aes_ctx->key_sched);
 669 
 670                         goto clean1;
 671                 }
 672 
 673                 out_len = AES_BLOCK_LEN;
 674 
 675                 /*
 676                  * If application asks for the length of the output buffer
 677                  * to hold the plaintext?
 678                  */
 679                 if (pLastPart == NULL) {
 680                         *pulLastPartLen = out_len;
 681                         rv = CKR_OK;
 682                         goto clean2;
 683                 } else {
 684                         crypto_data_t out;
 685 
 686                         /* Copy remaining data to the output buffer. */
 687                         (void) memcpy(pLastPart, soft_aes_ctx->data,
 688                             AES_BLOCK_LEN);
 689 
 690                         out.cd_format = CRYPTO_DATA_RAW;
 691                         out.cd_offset = 0;
 692                         out.cd_length = AES_BLOCK_LEN;
 693                         out.cd_raw.iov_base = (char *)pLastPart;
 694                         out.cd_raw.iov_len = AES_BLOCK_LEN;
 695 
 696                         /* Decrypt final block of data. */
 697                         rc = aes_decrypt_contiguous_blocks(
 698                             (aes_ctx_t *)soft_aes_ctx->aes_cbc,
 699                             (char *)pLastPart, AES_BLOCK_LEN, &out);
 700 
 701                         if (rc == 0) {
 702                                 /*
 703                                  * Remove padding bytes after decryption of
 704                                  * ciphertext block to produce the original
 705                                  * plaintext.
 706                                  */
 707                                 rv = soft_remove_pkcs7_padding(pLastPart,
 708                                     AES_BLOCK_LEN, &out_len);
 709                                 if (rv != CKR_OK)
 710                                         *pulLastPartLen = 0;
 711                                 else
 712                                         *pulLastPartLen = out_len;
 713                         } else {
 714                                 *pulLastPartLen = 0;
 715                                 rv = CKR_FUNCTION_FAILED;
 716                         }
 717 
 718                         /* Cleanup memory space. */
 719                         free(soft_aes_ctx->aes_cbc);
 720                         bzero(soft_aes_ctx->key_sched,
 721                             soft_aes_ctx->keysched_len);
 722                         free(soft_aes_ctx->key_sched);
 723 
 724                 }
 725 
 726                 break;
 727         }
 728 
 729         case CKM_AES_CBC:
 730         case CKM_AES_ECB:
 731         {
 732                 soft_aes_ctx_t *soft_aes_ctx;
 733 
 734                 soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
 735                 /*
 736                  * CKM_AES_CBC and CKM_AES_ECB does not do any padding,
 737                  * so when the final is called, the remaining buffer
 738                  * should not contain any more data.
 739                  */
 740                 *pulLastPartLen = 0;
 741                 if (soft_aes_ctx->remain_len != 0) {
 742                         rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
 743                 } else {
 744                         if (pLastPart == NULL)
 745                                 goto clean2;
 746                 }
 747 
 748                 /* Cleanup memory space. */
 749                 free(soft_aes_ctx->aes_cbc);
 750                 bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len);
 751                 free(soft_aes_ctx->key_sched);
 752 
 753                 break;
 754         }
 755         case CKM_AES_CTR:
 756         {
 757                 crypto_data_t out;
 758                 soft_aes_ctx_t *soft_aes_ctx;
 759                 ctr_ctx_t *ctr_ctx;
 760                 size_t len;
 761 
 762                 soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
 763                 ctr_ctx = soft_aes_ctx->aes_cbc;
 764                 len = ctr_ctx->ctr_remainder_len;
 765                 if (pLastPart == NULL) {
 766                         *pulLastPartLen = len;
 767                         goto clean1;
 768                 }
 769                 if (len > 0) {
 770                         out.cd_format = CRYPTO_DATA_RAW;
 771                         out.cd_offset = 0;
 772                         out.cd_length = len;
 773                         out.cd_raw.iov_base = (char *)pLastPart;
 774                         out.cd_raw.iov_len = len;
 775 
 776                         rv = ctr_mode_final(ctr_ctx, &out, aes_encrypt_block);
 777                         if (rv == CRYPTO_DATA_LEN_RANGE)
 778                                 rv = CRYPTO_ENCRYPTED_DATA_LEN_RANGE;
 779                 }
 780                 if (rv == CRYPTO_BUFFER_TOO_SMALL) {
 781                         *pulLastPartLen = len;
 782                         goto clean1;
 783                 }
 784 
 785                 /* Cleanup memory space. */
 786                 free(ctr_ctx);
 787                 bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len);
 788                 free(soft_aes_ctx->key_sched);
 789 
 790                 break;
 791         }
 792         case CKM_BLOWFISH_CBC:
 793         {
 794                 soft_blowfish_ctx_t *soft_blowfish_ctx;
 795 
 796                 soft_blowfish_ctx =
 797                     (soft_blowfish_ctx_t *)session_p->decrypt.context;
 798 
 799                 *pulLastPartLen = 0;
 800                 if (soft_blowfish_ctx->remain_len != 0)
 801                         rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
 802                 else {
 803                         if (pLastPart == NULL)
 804                                 goto clean2;
 805                 }
 806 
 807                 free(soft_blowfish_ctx->blowfish_cbc);
 808                 bzero(soft_blowfish_ctx->key_sched,
 809                     soft_blowfish_ctx->keysched_len);
 810                 free(soft_blowfish_ctx->key_sched);
 811 
 812                 break;
 813         }
 814 
 815         case CKM_RC4:
 816         {
 817                 ARCFour_key *key = (ARCFour_key *)session_p->decrypt.context;
 818                 bzero(key, sizeof (*key));
 819                 *pulLastPartLen = 0;
 820                 break;
 821         }
 822 
 823         default:
 824                 /* PKCS11: The mechanism only supports single-part operation. */
 825                 rv = CKR_MECHANISM_INVALID;
 826                 break;
 827         }
 828 
 829 clean1:
 830         free(session_p->decrypt.context);
 831         session_p->decrypt.context = NULL;
 832 
 833 clean2:
 834         (void) pthread_mutex_unlock(&session_p->session_mutex);
 835 
 836         return (rv);
 837 
 838 }