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 2015 Nexenta Systems, Inc.  All rights reserved.
  25  * Copyright (c) 2018, Joyent, Inc.
  26  */
  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 <modes/modes.h>
  35 #include <arcfour.h>
  36 #include "softSession.h"
  37 #include "softObject.h"
  38 #include "softOps.h"
  39 #include "softCrypt.h"
  40 #include "softRSA.h"
  41 
  42 /*
  43  * Add padding bytes with the value of length of padding.
  44  */
  45 void
  46 soft_add_pkcs7_padding(CK_BYTE *buf, int block_size, CK_ULONG data_len)
  47 {
  48         (void) pkcs7_encode(NULL, data_len, buf, block_size, block_size);
  49 }
  50 
  51 /*
  52  * Perform encrypt init operation internally for the support of
  53  * CKM_AES and CKM_DES MAC operations.
  54  *
  55  * This function is called with the session being held, and without
  56  * its mutex taken.
  57  */
  58 CK_RV
  59 soft_encrypt_init_internal(soft_session_t *session_p, CK_MECHANISM_PTR
  60     pMechanism, soft_object_t *key_p)
  61 {
  62         CK_RV rv;
  63 
  64         (void) pthread_mutex_lock(&session_p->session_mutex);
  65 
  66         /* Check to see if encrypt operation is already active */
  67         if (session_p->encrypt.flags & CRYPTO_OPERATION_ACTIVE) {
  68                 (void) pthread_mutex_unlock(&session_p->session_mutex);
  69                 return (CKR_OPERATION_ACTIVE);
  70         }
  71 
  72         session_p->encrypt.flags = CRYPTO_OPERATION_ACTIVE;
  73 
  74         (void) pthread_mutex_unlock(&session_p->session_mutex);
  75 
  76         rv = soft_encrypt_init(session_p, pMechanism, key_p);
  77 
  78         if (rv != CKR_OK) {
  79                 (void) pthread_mutex_lock(&session_p->session_mutex);
  80                 session_p->encrypt.flags &= ~CRYPTO_OPERATION_ACTIVE;
  81                 (void) pthread_mutex_unlock(&session_p->session_mutex);
  82         }
  83 
  84         return (rv);
  85 }
  86 
  87 /*
  88  * soft_encrypt_init()
  89  *
  90  * Arguments:
  91  *      session_p:      pointer to soft_session_t struct
  92  *      pMechanism:     pointer to CK_MECHANISM struct provided by application
  93  *      key_p:          pointer to key soft_object_t struct
  94  *
  95  * Description:
  96  *      called by C_EncryptInit(). This function calls the corresponding
  97  *      encrypt init routine based on the mechanism.
  98  *
  99  * Returns:
 100  *      CKR_OK: success
 101  *      CKR_HOST_MEMORY: run out of system memory
 102  *      CKR_MECHANISM_PARAM_INVALID: invalid parameters in mechanism
 103  *      CKR_MECHANISM_INVALID: invalid mechanism type
 104  *      CKR_KEY_TYPE_INCONSISTENT: incorrect type of key to use
 105  *              with the specified mechanism
 106  */
 107 CK_RV
 108 soft_encrypt_init(soft_session_t *session_p, CK_MECHANISM_PTR pMechanism,
 109     soft_object_t *key_p)
 110 {
 111 
 112         CK_RV rv;
 113 
 114         switch (pMechanism->mechanism) {
 115 
 116         case CKM_DES_ECB:
 117 
 118                 if (key_p->key_type != CKK_DES) {
 119                         return (CKR_KEY_TYPE_INCONSISTENT);
 120                 }
 121                 goto ecb_common;
 122 
 123         case CKM_DES3_ECB:
 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 ecb_common:
 131                 return (soft_des_crypt_init_common(session_p, pMechanism,
 132                     key_p, B_TRUE));
 133 
 134         case CKM_DES_CBC:
 135         case CKM_DES_CBC_PAD:
 136 
 137                 if (key_p->key_type != CKK_DES) {
 138                         return (CKR_KEY_TYPE_INCONSISTENT);
 139                 }
 140 
 141                 goto cbc_common;
 142 
 143         case CKM_DES3_CBC:
 144         case CKM_DES3_CBC_PAD:
 145         {
 146 
 147                 soft_des_ctx_t *soft_des_ctx;
 148 
 149                 if ((key_p->key_type != CKK_DES2) &&
 150                     (key_p->key_type != CKK_DES3)) {
 151                         return (CKR_KEY_TYPE_INCONSISTENT);
 152                 }
 153 
 154 cbc_common:
 155                 if ((pMechanism->pParameter == NULL) ||
 156                     (pMechanism->ulParameterLen != DES_BLOCK_LEN)) {
 157                         return (CKR_MECHANISM_PARAM_INVALID);
 158                 }
 159 
 160                 rv = soft_des_crypt_init_common(session_p, pMechanism,
 161                     key_p, B_TRUE);
 162 
 163                 if (rv != CKR_OK)
 164                         return (rv);
 165 
 166                 (void) pthread_mutex_lock(&session_p->session_mutex);
 167 
 168                 soft_des_ctx = (soft_des_ctx_t *)session_p->encrypt.context;
 169                 /* Copy Initialization Vector (IV) into the context. */
 170                 (void) memcpy(soft_des_ctx->ivec, pMechanism->pParameter,
 171                     DES_BLOCK_LEN);
 172 
 173                 /* Allocate a context for DES cipher-block chaining. */
 174                 soft_des_ctx->des_cbc = (void *)des_cbc_ctx_init(
 175                     soft_des_ctx->key_sched, soft_des_ctx->keysched_len,
 176                     soft_des_ctx->ivec, key_p->key_type);
 177 
 178                 if (soft_des_ctx->des_cbc == NULL) {
 179                         freezero(soft_des_ctx->key_sched,
 180                             soft_des_ctx->keysched_len);
 181                         freezero(session_p->encrypt.context,
 182                             sizeof (soft_des_ctx_t));
 183                         session_p->encrypt.context = NULL;
 184                         rv = CKR_HOST_MEMORY;
 185                 }
 186 
 187                 (void) pthread_mutex_unlock(&session_p->session_mutex);
 188 
 189                 return (rv);
 190         }
 191         case CKM_AES_ECB:
 192 
 193                 if (key_p->key_type != CKK_AES) {
 194                         return (CKR_KEY_TYPE_INCONSISTENT);
 195                 }
 196 
 197                 return (soft_aes_crypt_init_common(session_p, pMechanism,
 198                     key_p, B_TRUE));
 199 
 200         case CKM_AES_CBC:
 201         case CKM_AES_CBC_PAD:
 202                 if ((pMechanism->pParameter == NULL) ||
 203                     (pMechanism->ulParameterLen != AES_BLOCK_LEN)) {
 204                         return (CKR_MECHANISM_PARAM_INVALID);
 205                 }
 206         /* FALLTHRU */
 207         case CKM_AES_CMAC:
 208         {
 209                 soft_aes_ctx_t *soft_aes_ctx;
 210 
 211                 if (key_p->key_type != CKK_AES) {
 212                         return (CKR_KEY_TYPE_INCONSISTENT);
 213                 }
 214 
 215 
 216                 rv = soft_aes_crypt_init_common(session_p, pMechanism,
 217                     key_p, B_TRUE);
 218 
 219                 if (rv != CKR_OK)
 220                         return (rv);
 221 
 222                 (void) pthread_mutex_lock(&session_p->session_mutex);
 223 
 224                 soft_aes_ctx = (soft_aes_ctx_t *)session_p->encrypt.context;
 225                 /* Copy Initialization Vector (IV) into the context. */
 226                 if (pMechanism->mechanism == CKM_AES_CMAC) {
 227                         (void) bzero(soft_aes_ctx->ivec, AES_BLOCK_LEN);
 228                         /* Allocate a context for AES cipher-block chaining. */
 229                         soft_aes_ctx->aes_cbc = (void *)aes_cmac_ctx_init(
 230                             soft_aes_ctx->key_sched,
 231                             soft_aes_ctx->keysched_len);
 232                 } else {
 233                         (void) memcpy(soft_aes_ctx->ivec,
 234                             pMechanism->pParameter,
 235                             AES_BLOCK_LEN);
 236                         /* Allocate a context for AES cipher-block chaining. */
 237                         soft_aes_ctx->aes_cbc = (void *)aes_cbc_ctx_init(
 238                             soft_aes_ctx->key_sched,
 239                             soft_aes_ctx->keysched_len,
 240                             soft_aes_ctx->ivec);
 241                 }
 242                 if (soft_aes_ctx->aes_cbc == NULL) {
 243                         freezero(soft_aes_ctx->key_sched,
 244                             soft_aes_ctx->keysched_len);
 245                         freezero(session_p->encrypt.context,
 246                             sizeof (soft_aes_ctx_t));
 247                         session_p->encrypt.context = NULL;
 248                         rv = CKR_HOST_MEMORY;
 249                 }
 250 
 251                 (void) pthread_mutex_unlock(&session_p->session_mutex);
 252 
 253                 return (rv);
 254         }
 255         case CKM_AES_CTR:
 256         {
 257                 soft_aes_ctx_t *soft_aes_ctx;
 258 
 259                 if (key_p->key_type != CKK_AES) {
 260                         return (CKR_KEY_TYPE_INCONSISTENT);
 261                 }
 262 
 263                 if (pMechanism->pParameter == NULL ||
 264                     pMechanism->ulParameterLen != sizeof (CK_AES_CTR_PARAMS)) {
 265                         return (CKR_MECHANISM_PARAM_INVALID);
 266                 }
 267 
 268                 rv = soft_aes_crypt_init_common(session_p, pMechanism,
 269                     key_p, B_TRUE);
 270 
 271                 if (rv != CKR_OK)
 272                         return (rv);
 273 
 274                 (void) pthread_mutex_lock(&session_p->session_mutex);
 275 
 276                 soft_aes_ctx = (soft_aes_ctx_t *)session_p->encrypt.context;
 277                 soft_aes_ctx->aes_cbc = aes_ctr_ctx_init(
 278                     soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len,
 279                     pMechanism->pParameter);
 280 
 281                 if (soft_aes_ctx->aes_cbc == NULL) {
 282                         freezero(soft_aes_ctx->key_sched,
 283                             soft_aes_ctx->keysched_len);
 284                         freezero(session_p->encrypt.context,
 285                             sizeof (soft_aes_ctx_t));
 286                         session_p->encrypt.context = NULL;
 287                         rv = CKR_HOST_MEMORY;
 288                 }
 289 
 290                 (void) pthread_mutex_unlock(&session_p->session_mutex);
 291 
 292                 return (rv);
 293         }
 294         case CKM_RC4:
 295 
 296                 if (key_p->key_type != CKK_RC4) {
 297                         return (CKR_KEY_TYPE_INCONSISTENT);
 298                 }
 299 
 300                 return (soft_arcfour_crypt_init(session_p, pMechanism, key_p,
 301                     B_TRUE));
 302 
 303         case CKM_RSA_X_509:
 304         case CKM_RSA_PKCS:
 305 
 306                 if (key_p->key_type != CKK_RSA) {
 307                         return (CKR_KEY_TYPE_INCONSISTENT);
 308                 }
 309 
 310                 return (soft_rsa_crypt_init_common(session_p, pMechanism,
 311                     key_p, B_TRUE));
 312 
 313         case CKM_BLOWFISH_CBC:
 314         {
 315                 soft_blowfish_ctx_t *soft_blowfish_ctx;
 316 
 317                 if (key_p->key_type != CKK_BLOWFISH)
 318                         return (CKR_KEY_TYPE_INCONSISTENT);
 319 
 320                 if ((pMechanism->pParameter == NULL) ||
 321                     (pMechanism->ulParameterLen != BLOWFISH_BLOCK_LEN))
 322                         return (CKR_MECHANISM_PARAM_INVALID);
 323 
 324                 rv = soft_blowfish_crypt_init_common(session_p, pMechanism,
 325                     key_p, B_TRUE);
 326 
 327                 if (rv != CKR_OK)
 328                         return (rv);
 329 
 330                 (void) pthread_mutex_lock(&session_p->session_mutex);
 331 
 332                 soft_blowfish_ctx =
 333                     (soft_blowfish_ctx_t *)session_p->encrypt.context;
 334                 /* Copy Initialization Vector (IV) into the context. */
 335                 (void) memcpy(soft_blowfish_ctx->ivec, pMechanism->pParameter,
 336                     BLOWFISH_BLOCK_LEN);
 337 
 338                 /* Allocate a context for Blowfish cipher-block chaining */
 339                 soft_blowfish_ctx->blowfish_cbc =
 340                     (void *)blowfish_cbc_ctx_init(soft_blowfish_ctx->key_sched,
 341                     soft_blowfish_ctx->keysched_len,
 342                     soft_blowfish_ctx->ivec);
 343 
 344                 if (soft_blowfish_ctx->blowfish_cbc == NULL) {
 345                         freezero(soft_blowfish_ctx->key_sched,
 346                             soft_blowfish_ctx->keysched_len);
 347                         freezero(session_p->encrypt.context,
 348                             sizeof (soft_blowfish_ctx_t));
 349                         session_p->encrypt.context = NULL;
 350                         rv = CKR_HOST_MEMORY;
 351                 }
 352 
 353                 (void) pthread_mutex_unlock(&session_p->session_mutex);
 354 
 355                 return (rv);
 356         }
 357         default:
 358                 return (CKR_MECHANISM_INVALID);
 359         }
 360 }
 361 
 362 
 363 /*
 364  * soft_encrypt_common()
 365  *
 366  * Arguments:
 367  *      session_p:      pointer to soft_session_t struct
 368  *      pData:          pointer to the input data to be encrypted
 369  *      ulDataLen:      length of the input data
 370  *      pEncrypted:     pointer to the output data after encryption
 371  *      pulEncryptedLen: pointer to the length of the output data
 372  *      update:         boolean flag indicates caller is soft_encrypt
 373  *                      or soft_encrypt_update
 374  *
 375  * Description:
 376  *      This function calls the corresponding encrypt routine based
 377  *      on the mechanism.
 378  *
 379  * Returns:
 380  *      see corresponding encrypt routine.
 381  */
 382 CK_RV
 383 soft_encrypt_common(soft_session_t *session_p, CK_BYTE_PTR pData,
 384     CK_ULONG ulDataLen, CK_BYTE_PTR pEncrypted,
 385     CK_ULONG_PTR pulEncryptedLen, boolean_t update)
 386 {
 387 
 388         CK_MECHANISM_TYPE mechanism = session_p->encrypt.mech.mechanism;
 389 
 390         switch (mechanism) {
 391 
 392         case CKM_DES_ECB:
 393         case CKM_DES_CBC:
 394         case CKM_DES3_ECB:
 395         case CKM_DES3_CBC:
 396 
 397                 if (ulDataLen == 0) {
 398                         *pulEncryptedLen = 0;
 399                         return (CKR_OK);
 400                 }
 401                 /* FALLTHROUGH */
 402 
 403         case CKM_DES_CBC_PAD:
 404         case CKM_DES3_CBC_PAD:
 405 
 406                 return (soft_des_encrypt_common(session_p, pData,
 407                     ulDataLen, pEncrypted, pulEncryptedLen, update));
 408 
 409         case CKM_AES_ECB:
 410         case CKM_AES_CBC:
 411         case CKM_AES_CTR:
 412 
 413                 if (ulDataLen == 0) {
 414                         *pulEncryptedLen = 0;
 415                         return (CKR_OK);
 416                 }
 417                 /* FALLTHROUGH */
 418 
 419         case CKM_AES_CMAC:
 420         case CKM_AES_CBC_PAD:
 421 
 422                 return (soft_aes_encrypt_common(session_p, pData,
 423                     ulDataLen, pEncrypted, pulEncryptedLen, update));
 424 
 425         case CKM_BLOWFISH_CBC:
 426 
 427                 if (ulDataLen == 0) {
 428                         *pulEncryptedLen = 0;
 429                         return (CKR_OK);
 430                 }
 431 
 432                 return (soft_blowfish_encrypt_common(session_p, pData,
 433                     ulDataLen, pEncrypted, pulEncryptedLen, update));
 434 
 435         case CKM_RC4:
 436 
 437                 if (ulDataLen == 0) {
 438                         *pulEncryptedLen = 0;
 439                         return (CKR_OK);
 440                 }
 441 
 442                 return (soft_arcfour_crypt(&(session_p->encrypt), pData,
 443                     ulDataLen, pEncrypted, pulEncryptedLen));
 444 
 445         case CKM_RSA_X_509:
 446         case CKM_RSA_PKCS:
 447 
 448                 return (soft_rsa_encrypt_common(session_p, pData,
 449                     ulDataLen, pEncrypted, pulEncryptedLen, mechanism));
 450 
 451         default:
 452                 return (CKR_MECHANISM_INVALID);
 453         }
 454 }
 455 
 456 
 457 /*
 458  * soft_encrypt()
 459  *
 460  * Arguments:
 461  *      session_p:      pointer to soft_session_t struct
 462  *      pData:          pointer to the input data to be encrypted
 463  *      ulDataLen:      length of the input data
 464  *      pEncryptedData: pointer to the output data after encryption
 465  *      pulEncryptedDataLen: pointer to the length of the output data
 466  *
 467  * Description:
 468  *      called by C_Encrypt(). This function calls the soft_encrypt_common
 469  *      routine.
 470  *
 471  * Returns:
 472  *      see soft_encrypt_common().
 473  */
 474 CK_RV
 475 soft_encrypt(soft_session_t *session_p, CK_BYTE_PTR pData,
 476     CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData,
 477     CK_ULONG_PTR pulEncryptedDataLen)
 478 {
 479 
 480         return (soft_encrypt_common(session_p, pData, ulDataLen,
 481             pEncryptedData, pulEncryptedDataLen, B_FALSE));
 482 }
 483 
 484 
 485 /*
 486  * soft_encrypt_update()
 487  *
 488  * Arguments:
 489  *      session_p:      pointer to soft_session_t struct
 490  *      pPart:          pointer to the input data to be digested
 491  *      ulPartLen:      length of the input data
 492  *      pEncryptedPart: pointer to the ciphertext
 493  *      pulEncryptedPartLen: pointer to the length of the ciphertext
 494  *
 495  * Description:
 496  *      called by C_EncryptUpdate(). This function calls the
 497  *      soft_encrypt_common routine (with update flag on).
 498  *
 499  * Returns:
 500  *      see soft_encrypt_common().
 501  */
 502 CK_RV
 503 soft_encrypt_update(soft_session_t *session_p, CK_BYTE_PTR pPart,
 504     CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
 505     CK_ULONG_PTR pulEncryptedPartLen)
 506 {
 507 
 508         CK_MECHANISM_TYPE mechanism = session_p->encrypt.mech.mechanism;
 509 
 510         switch (mechanism) {
 511 
 512         case CKM_DES_ECB:
 513         case CKM_DES_CBC:
 514         case CKM_DES_CBC_PAD:
 515         case CKM_DES3_ECB:
 516         case CKM_DES3_CBC:
 517         case CKM_DES3_CBC_PAD:
 518         case CKM_AES_ECB:
 519         case CKM_AES_CBC:
 520         case CKM_AES_CBC_PAD:
 521         case CKM_AES_CMAC:
 522         case CKM_AES_CTR:
 523         case CKM_BLOWFISH_CBC:
 524         case CKM_RC4:
 525 
 526                 return (soft_encrypt_common(session_p, pPart, ulPartLen,
 527                     pEncryptedPart, pulEncryptedPartLen, B_TRUE));
 528 
 529         default:
 530                 /* PKCS11: The mechanism only supports single-part operation. */
 531                 return (CKR_MECHANISM_INVALID);
 532         }
 533 }
 534 
 535 
 536 /*
 537  * soft_encrypt_final()
 538  *
 539  * Arguments:
 540  *      session_p:              pointer to soft_session_t struct
 541  *      pLastEncryptedPart:     pointer to the last encrypted data part
 542  *      pulLastEncryptedPartLen: pointer to the length of the last
 543  *                              encrypted data part
 544  *
 545  * Description:
 546  *      called by C_EncryptFinal().
 547  *
 548  * Returns:
 549  *      CKR_OK: success
 550  *      CKR_FUNCTION_FAILED: encrypt final function failed
 551  *      CKR_DATA_LEN_RANGE: remaining buffer contains bad length
 552  */
 553 CK_RV
 554 soft_encrypt_final(soft_session_t *session_p, CK_BYTE_PTR pLastEncryptedPart,
 555     CK_ULONG_PTR pulLastEncryptedPartLen)
 556 {
 557 
 558         CK_MECHANISM_TYPE mechanism = session_p->encrypt.mech.mechanism;
 559         CK_ULONG out_len;
 560         CK_RV rv = CKR_OK;
 561         int rc;
 562 
 563         (void) pthread_mutex_lock(&session_p->session_mutex);
 564 
 565         if (session_p->encrypt.context == NULL) {
 566                 rv = CKR_OPERATION_NOT_INITIALIZED;
 567                 *pulLastEncryptedPartLen = 0;
 568                 goto clean1;
 569         }
 570         switch (mechanism) {
 571 
 572         case CKM_DES_CBC_PAD:
 573         case CKM_DES3_CBC_PAD:
 574         {
 575                 soft_des_ctx_t *soft_des_ctx;
 576 
 577                 soft_des_ctx = (soft_des_ctx_t *)session_p->encrypt.context;
 578                 /*
 579                  * For CKM_DES_CBC_PAD, compute output length with
 580                  * padding. If the remaining buffer has one block
 581                  * of data, then output length will be two blocksize of
 582                  * ciphertext. If the remaining buffer has less than
 583                  * one block of data, then output length will be
 584                  * one blocksize.
 585                  */
 586                 if (soft_des_ctx->remain_len == DES_BLOCK_LEN)
 587                         out_len = 2 * DES_BLOCK_LEN;
 588                 else
 589                         out_len = DES_BLOCK_LEN;
 590 
 591                 if (pLastEncryptedPart == NULL) {
 592                         /*
 593                          * Application asks for the length of the output
 594                          * buffer to hold the ciphertext.
 595                          */
 596                         *pulLastEncryptedPartLen = out_len;
 597                         goto clean1;
 598                 } else {
 599                         crypto_data_t out;
 600 
 601                         /* Copy remaining data to the output buffer. */
 602                         (void) memcpy(pLastEncryptedPart, soft_des_ctx->data,
 603                             soft_des_ctx->remain_len);
 604 
 605                         /*
 606                          * Add padding bytes prior to encrypt final.
 607                          */
 608                         soft_add_pkcs7_padding(pLastEncryptedPart +
 609                             soft_des_ctx->remain_len, DES_BLOCK_LEN,
 610                             soft_des_ctx->remain_len);
 611 
 612                         out.cd_format = CRYPTO_DATA_RAW;
 613                         out.cd_offset = 0;
 614                         out.cd_length = out_len;
 615                         out.cd_raw.iov_base = (char *)pLastEncryptedPart;
 616                         out.cd_raw.iov_len = out_len;
 617 
 618                         /* Encrypt multiple blocks of data. */
 619                         rc = des_encrypt_contiguous_blocks(
 620                             (des_ctx_t *)soft_des_ctx->des_cbc,
 621                             (char *)pLastEncryptedPart, out_len, &out);
 622 
 623                         if (rc == 0) {
 624                                 *pulLastEncryptedPartLen = out_len;
 625                         } else {
 626                                 *pulLastEncryptedPartLen = 0;
 627                                 rv = CKR_FUNCTION_FAILED;
 628                         }
 629 
 630                         /* Cleanup memory space. */
 631                         free(soft_des_ctx->des_cbc);
 632                         freezero(soft_des_ctx->key_sched,
 633                             soft_des_ctx->keysched_len);
 634                 }
 635 
 636                 break;
 637         }
 638         case CKM_DES_CBC:
 639         case CKM_DES_ECB:
 640         case CKM_DES3_CBC:
 641         case CKM_DES3_ECB:
 642         {
 643 
 644                 soft_des_ctx_t *soft_des_ctx;
 645 
 646                 soft_des_ctx = (soft_des_ctx_t *)session_p->encrypt.context;
 647                 /*
 648                  * CKM_DES_CBC and CKM_DES_ECB does not do any padding,
 649                  * so when the final is called, the remaining buffer
 650                  * should not contain any more data.
 651                  */
 652                 *pulLastEncryptedPartLen = 0;
 653                 if (soft_des_ctx->remain_len != 0) {
 654                         rv = CKR_DATA_LEN_RANGE;
 655                 } else {
 656                         if (pLastEncryptedPart == NULL)
 657                                 goto clean1;
 658                 }
 659 
 660                 /* Cleanup memory space. */
 661                 free(soft_des_ctx->des_cbc);
 662                 freezero(soft_des_ctx->key_sched,
 663                     soft_des_ctx->keysched_len);
 664 
 665                 break;
 666         }
 667         case CKM_AES_CBC_PAD:
 668         {
 669                 soft_aes_ctx_t *soft_aes_ctx;
 670 
 671                 soft_aes_ctx = (soft_aes_ctx_t *)session_p->encrypt.context;
 672                 /*
 673                  * For CKM_AES_CBC_PAD, compute output length with
 674                  * padding. If the remaining buffer has one block
 675                  * of data, then output length will be two blocksize of
 676                  * ciphertext. If the remaining buffer has less than
 677                  * one block of data, then output length will be
 678                  * one blocksize.
 679                  */
 680                 if (soft_aes_ctx->remain_len == AES_BLOCK_LEN)
 681                         out_len = 2 * AES_BLOCK_LEN;
 682                 else
 683                         out_len = AES_BLOCK_LEN;
 684 
 685                 if (pLastEncryptedPart == NULL) {
 686                         /*
 687                          * Application asks for the length of the output
 688                          * buffer to hold the ciphertext.
 689                          */
 690                         *pulLastEncryptedPartLen = out_len;
 691                         goto clean1;
 692                 } else {
 693                         crypto_data_t out;
 694 
 695                         /* Copy remaining data to the output buffer. */
 696                         (void) memcpy(pLastEncryptedPart, soft_aes_ctx->data,
 697                             soft_aes_ctx->remain_len);
 698 
 699                         /*
 700                          * Add padding bytes prior to encrypt final.
 701                          */
 702                         soft_add_pkcs7_padding(pLastEncryptedPart +
 703                             soft_aes_ctx->remain_len, AES_BLOCK_LEN,
 704                             soft_aes_ctx->remain_len);
 705 
 706                         out.cd_format = CRYPTO_DATA_RAW;
 707                         out.cd_offset = 0;
 708                         out.cd_length = out_len;
 709                         out.cd_raw.iov_base = (char *)pLastEncryptedPart;
 710                         out.cd_raw.iov_len = out_len;
 711 
 712                         /* Encrypt multiple blocks of data. */
 713                         rc = aes_encrypt_contiguous_blocks(
 714                             (aes_ctx_t *)soft_aes_ctx->aes_cbc,
 715                             (char *)pLastEncryptedPart, out_len, &out);
 716 
 717                         if (rc == 0) {
 718                                 *pulLastEncryptedPartLen = out_len;
 719                         } else {
 720                                 *pulLastEncryptedPartLen = 0;
 721                                 rv = CKR_FUNCTION_FAILED;
 722                         }
 723 
 724                         /* Cleanup memory space. */
 725                         free(soft_aes_ctx->aes_cbc);
 726                         freezero(soft_aes_ctx->key_sched,
 727                             soft_aes_ctx->keysched_len);
 728                 }
 729 
 730                 break;
 731         }
 732         case CKM_AES_CMAC:
 733         {
 734                 soft_aes_ctx_t *soft_aes_ctx;
 735                 soft_aes_ctx = (soft_aes_ctx_t *)session_p->encrypt.context;
 736 
 737                 if (pLastEncryptedPart == NULL) {
 738                         /*
 739                          * Application asks for the length of the output
 740                          * buffer to hold the ciphertext.
 741                          */
 742                         *pulLastEncryptedPartLen = AES_BLOCK_LEN;
 743                         goto clean1;
 744                 } else {
 745                         crypto_data_t out;
 746 
 747                         out.cd_format = CRYPTO_DATA_RAW;
 748                         out.cd_offset = 0;
 749                         out.cd_length = AES_BLOCK_LEN;
 750                         out.cd_raw.iov_base = (char *)pLastEncryptedPart;
 751                         out.cd_raw.iov_len = AES_BLOCK_LEN;
 752 
 753                         rc = cmac_mode_final(soft_aes_ctx->aes_cbc, &out,
 754                             aes_encrypt_block, aes_xor_block);
 755 
 756                         if (rc == 0) {
 757                                 *pulLastEncryptedPartLen = AES_BLOCK_LEN;
 758                         } else {
 759                                 *pulLastEncryptedPartLen = 0;
 760                                 rv = CKR_FUNCTION_FAILED;
 761                         }
 762 
 763                         /* Cleanup memory space. */
 764                         free(soft_aes_ctx->aes_cbc);
 765                         freezero(soft_aes_ctx->key_sched,
 766                             soft_aes_ctx->keysched_len);
 767                 }
 768 
 769                 break;
 770         }
 771         case CKM_AES_CBC:
 772         case CKM_AES_ECB:
 773         {
 774                 soft_aes_ctx_t *soft_aes_ctx;
 775 
 776                 soft_aes_ctx = (soft_aes_ctx_t *)session_p->encrypt.context;
 777                 /*
 778                  * CKM_AES_CBC and CKM_AES_ECB does not do any padding,
 779                  * so when the final is called, the remaining buffer
 780                  * should not contain any more data.
 781                  */
 782                 *pulLastEncryptedPartLen = 0;
 783                 if (soft_aes_ctx->remain_len != 0) {
 784                         rv = CKR_DATA_LEN_RANGE;
 785                 } else {
 786                         if (pLastEncryptedPart == NULL)
 787                                 goto clean1;
 788                 }
 789 
 790                 /* Cleanup memory space. */
 791                 free(soft_aes_ctx->aes_cbc);
 792                 freezero(soft_aes_ctx->key_sched,
 793                     soft_aes_ctx->keysched_len);
 794 
 795                 break;
 796         }
 797         case CKM_AES_CTR:
 798         {
 799                 crypto_data_t out;
 800                 soft_aes_ctx_t *soft_aes_ctx;
 801                 ctr_ctx_t *ctr_ctx;
 802                 size_t len;
 803 
 804                 soft_aes_ctx = (soft_aes_ctx_t *)session_p->encrypt.context;
 805                 ctr_ctx = soft_aes_ctx->aes_cbc;
 806                 len = ctr_ctx->ctr_remainder_len;
 807 
 808                 if (pLastEncryptedPart == NULL) {
 809                         *pulLastEncryptedPartLen = len;
 810                         goto clean1;
 811                 }
 812                 if (len > 0) {
 813                         out.cd_format = CRYPTO_DATA_RAW;
 814                         out.cd_offset = 0;
 815                         out.cd_length = len;
 816                         out.cd_raw.iov_base = (char *)pLastEncryptedPart;
 817                         out.cd_raw.iov_len = len;
 818 
 819                         rv = ctr_mode_final(ctr_ctx, &out, aes_encrypt_block);
 820                 }
 821                 if (rv == CRYPTO_BUFFER_TOO_SMALL) {
 822                         *pulLastEncryptedPartLen = len;
 823                         goto clean1;
 824                 }
 825 
 826                 /* Cleanup memory space. */
 827                 free(ctr_ctx);
 828                 freezero(soft_aes_ctx->key_sched,
 829                     soft_aes_ctx->keysched_len);
 830 
 831                 break;
 832         }
 833         case CKM_BLOWFISH_CBC:
 834         {
 835                 soft_blowfish_ctx_t *soft_blowfish_ctx;
 836 
 837                 soft_blowfish_ctx =
 838                     (soft_blowfish_ctx_t *)session_p->encrypt.context;
 839                 /*
 840                  * CKM_BLOWFISH_CBC does not do any padding, so when the
 841                  * final is called, the remaining buffer should not contain
 842                  * any more data
 843                  */
 844                 *pulLastEncryptedPartLen = 0;
 845                 if (soft_blowfish_ctx->remain_len != 0)
 846                         rv = CKR_DATA_LEN_RANGE;
 847                 else {
 848                         if (pLastEncryptedPart == NULL)
 849                                 goto clean1;
 850                 }
 851 
 852                 free(soft_blowfish_ctx->blowfish_cbc);
 853                 freezero(soft_blowfish_ctx->key_sched,
 854                     soft_blowfish_ctx->keysched_len);
 855                 break;
 856         }
 857 
 858         case CKM_RC4:
 859         {
 860                 ARCFour_key *key = (ARCFour_key *)session_p->encrypt.context;
 861                 /* Remaining data size is always zero for RC4. */
 862                 *pulLastEncryptedPartLen = 0;
 863                 if (pLastEncryptedPart == NULL)
 864                         goto clean1;
 865                 explicit_bzero(key, sizeof (*key));
 866                 break;
 867         }
 868         default:
 869                 /* PKCS11: The mechanism only supports single-part operation. */
 870                 rv = CKR_MECHANISM_INVALID;
 871                 break;
 872         }
 873 
 874         free(session_p->encrypt.context);
 875         session_p->encrypt.context = NULL;
 876 clean1:
 877         (void) pthread_mutex_unlock(&session_p->session_mutex);
 878 
 879         return (rv);
 880 }
 881 
 882 /*
 883  * This function frees the allocated active crypto context and the
 884  * lower level of allocated struct as needed.
 885  * This function is called by the 1st tier of encrypt/decrypt routines
 886  * or by the 2nd tier of session close routine. Since the 1st tier
 887  * caller will always call this function without locking the session
 888  * mutex and the 2nd tier caller will call with the lock, we add the
 889  * third parameter "lock_held" to distinguish this case.
 890  */
 891 void
 892 soft_crypt_cleanup(soft_session_t *session_p, boolean_t encrypt,
 893     boolean_t lock_held)
 894 {
 895 
 896         crypto_active_op_t *active_op;
 897         boolean_t lock_true = B_TRUE;
 898 
 899         if (!lock_held)
 900                 (void) pthread_mutex_lock(&session_p->session_mutex);
 901 
 902         active_op = (encrypt) ? &(session_p->encrypt) : &(session_p->decrypt);
 903 
 904         switch (active_op->mech.mechanism) {
 905 
 906         case CKM_DES_CBC_PAD:
 907         case CKM_DES3_CBC_PAD:
 908         case CKM_DES_CBC:
 909         case CKM_DES_ECB:
 910         case CKM_DES3_CBC:
 911         case CKM_DES3_ECB:
 912         {
 913 
 914                 soft_des_ctx_t *soft_des_ctx =
 915                     (soft_des_ctx_t *)active_op->context;
 916                 des_ctx_t *des_ctx;
 917 
 918                 if (soft_des_ctx != NULL) {
 919                         des_ctx = (des_ctx_t *)soft_des_ctx->des_cbc;
 920                         if (des_ctx != NULL) {
 921                                 explicit_bzero(des_ctx->dc_keysched,
 922                                     des_ctx->dc_keysched_len);
 923                                 free(soft_des_ctx->des_cbc);
 924                         }
 925                         freezero(soft_des_ctx->key_sched,
 926                             soft_des_ctx->keysched_len);
 927                 }
 928                 break;
 929         }
 930 
 931         case CKM_AES_CBC_PAD:
 932         case CKM_AES_CBC:
 933         case CKM_AES_CMAC:
 934         case CKM_AES_ECB:
 935         {
 936                 soft_aes_ctx_t *soft_aes_ctx =
 937                     (soft_aes_ctx_t *)active_op->context;
 938                 aes_ctx_t *aes_ctx;
 939 
 940                 if (soft_aes_ctx != NULL) {
 941                         aes_ctx = (aes_ctx_t *)soft_aes_ctx->aes_cbc;
 942                         if (aes_ctx != NULL) {
 943                                 explicit_bzero(aes_ctx->ac_keysched,
 944                                     aes_ctx->ac_keysched_len);
 945                                 free(soft_aes_ctx->aes_cbc);
 946                         }
 947                         freezero(soft_aes_ctx->key_sched,
 948                             soft_aes_ctx->keysched_len);
 949                 }
 950                 break;
 951         }
 952 
 953         case CKM_BLOWFISH_CBC:
 954         {
 955                 soft_blowfish_ctx_t *soft_blowfish_ctx =
 956                     (soft_blowfish_ctx_t *)active_op->context;
 957                 blowfish_ctx_t *blowfish_ctx;
 958 
 959                 if (soft_blowfish_ctx != NULL) {
 960                         blowfish_ctx =
 961                             (blowfish_ctx_t *)soft_blowfish_ctx->blowfish_cbc;
 962                         if (blowfish_ctx != NULL) {
 963                                 explicit_bzero(blowfish_ctx->bc_keysched,
 964                                     blowfish_ctx->bc_keysched_len);
 965                                 free(soft_blowfish_ctx->blowfish_cbc);
 966                         }
 967 
 968                         freezero(soft_blowfish_ctx->key_sched,
 969                             soft_blowfish_ctx->keysched_len);
 970                 }
 971                 break;
 972         }
 973 
 974         case CKM_RC4:
 975         {
 976                 ARCFour_key *key = (ARCFour_key *)active_op->context;
 977 
 978                 if (key != NULL)
 979                         explicit_bzero(key, sizeof (*key));
 980                 break;
 981         }
 982 
 983         case CKM_RSA_X_509:
 984         case CKM_RSA_PKCS:
 985         {
 986                 soft_rsa_ctx_t *rsa_ctx =
 987                     (soft_rsa_ctx_t *)active_op->context;
 988 
 989                 if (rsa_ctx != NULL)
 990                         if (rsa_ctx->key != NULL) {
 991                                 soft_cleanup_object(rsa_ctx->key);
 992                                 free(rsa_ctx->key);
 993                         }
 994 
 995                 break;
 996         }
 997 
 998         } /* switch */
 999 
1000         if (active_op->context != NULL) {
1001                 free(active_op->context);
1002                 active_op->context = NULL;
1003         }
1004 
1005         active_op->flags = 0;
1006 
1007         if (!lock_held)
1008                 SES_REFRELE(session_p, lock_true);
1009 }