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