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