1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  24  */
  25 
  26 #include <pthread.h>
  27 #include <stdlib.h>
  28 #include <string.h>
  29 #include <strings.h>
  30 #include <sys/types.h>
  31 #include <security/cryptoki.h>
  32 #include <modes/modes.h>
  33 #include <des_impl.h>
  34 #include "softSession.h"
  35 #include "softObject.h"
  36 #include "softCrypt.h"
  37 #include "softOps.h"
  38 
  39 /*
  40  * Allocate context for the active encryption or decryption operation, and
  41  * generate DES or DES3 key schedule to speed up the operation.
  42  */
  43 CK_RV
  44 soft_des_crypt_init_common(soft_session_t *session_p,
  45     CK_MECHANISM_PTR pMechanism, soft_object_t *key_p,
  46     boolean_t encrypt)
  47 {
  48 
  49         size_t size;
  50         soft_des_ctx_t *soft_des_ctx;
  51 
  52         soft_des_ctx = calloc(1, sizeof (soft_des_ctx_t));
  53         if (soft_des_ctx == NULL) {
  54                 return (CKR_HOST_MEMORY);
  55         }
  56 
  57         /* Allocate key schedule for DES or DES3 based on key type. */
  58         if (key_p->key_type == CKK_DES)
  59                 soft_des_ctx->key_sched = des_alloc_keysched(&size, DES, 0);
  60         else
  61                 soft_des_ctx->key_sched = des_alloc_keysched(&size, DES3, 0);
  62 
  63         if (soft_des_ctx->key_sched == NULL) {
  64                 free(soft_des_ctx);
  65                 return (CKR_HOST_MEMORY);
  66         }
  67 
  68         soft_des_ctx->keysched_len = size;
  69         soft_des_ctx->key_type = key_p->key_type;
  70 
  71         (void) pthread_mutex_lock(&session_p->session_mutex);
  72         if (encrypt) {
  73                 /* Called by C_EncryptInit. */
  74                 session_p->encrypt.context = soft_des_ctx;
  75                 session_p->encrypt.mech.mechanism = pMechanism->mechanism;
  76         } else {
  77                 /* Called by C_DecryptInit. */
  78                 session_p->decrypt.context = soft_des_ctx;
  79                 session_p->decrypt.mech.mechanism = pMechanism->mechanism;
  80         }
  81         (void) pthread_mutex_unlock(&session_p->session_mutex);
  82 
  83         /*
  84          * If this is a non-sensitive key and it does NOT have
  85          * a key schedule yet, then allocate one and expand it.
  86          * Otherwise, if its a non-sensitive key, and it DOES have
  87          * a key schedule already attached to it, just copy the
  88          * pre-expanded schedule to the context and avoid the
  89          * extra key schedule expansion operation.
  90          */
  91         if (!(key_p->bool_attr_mask & SENSITIVE_BOOL_ON)) {
  92                 if (OBJ_KEY_SCHED(key_p) == NULL) {
  93                         void *ks;
  94                         (void) pthread_mutex_lock(&key_p->object_mutex);
  95                         if (OBJ_KEY_SCHED(key_p) == NULL) {
  96                                 if (key_p->key_type == CKK_DES)
  97                                         ks = des_alloc_keysched(&size, DES, 0);
  98                                 else
  99                                         ks = des_alloc_keysched(&size, DES3, 0);
 100                                 if (ks == NULL) {
 101                                         (void) pthread_mutex_unlock(
 102                                             &key_p->object_mutex);
 103                                         free(soft_des_ctx);
 104                                         return (CKR_HOST_MEMORY);
 105                                 }
 106                                 /* Initialize key schedule for DES or DES3. */
 107                                 if (key_p->key_type == CKK_DES)
 108                                         des_init_keysched(
 109                                             OBJ_SEC(key_p)->sk_value, DES, ks);
 110                                 else if (key_p->key_type == CKK_DES2)
 111                                         /*
 112                                          * DES3 encryption/decryption needs to
 113                                          * support a DES2 key.
 114                                          */
 115                                         des_init_keysched(
 116                                             OBJ_SEC(key_p)->sk_value, DES2, ks);
 117                                 else
 118                                         des_init_keysched(
 119                                             OBJ_SEC(key_p)->sk_value, DES3, ks);
 120 
 121                                 OBJ_KEY_SCHED_LEN(key_p) = size;
 122                                 OBJ_KEY_SCHED(key_p) = ks;
 123                         }
 124                         (void) pthread_mutex_unlock(&key_p->object_mutex);
 125                 }
 126 
 127                 /* Copy the pre-expanded key schedule from the key object */
 128                 (void) memcpy(soft_des_ctx->key_sched, OBJ_KEY_SCHED(key_p),
 129                     OBJ_KEY_SCHED_LEN(key_p));
 130                 soft_des_ctx->keysched_len = OBJ_KEY_SCHED_LEN(key_p);
 131         } else {
 132                 /* for sensitive keys, we cannot cache the key schedule */
 133                 if (key_p->key_type == CKK_DES)
 134                         des_init_keysched(OBJ_SEC(key_p)->sk_value,
 135                             DES, soft_des_ctx->key_sched);
 136                 else if (key_p->key_type == CKK_DES2)
 137                         /*
 138                          * DES3 encryption/decryption needs to
 139                          * support a DES2 key.
 140                          */
 141                         des_init_keysched(OBJ_SEC(key_p)->sk_value,
 142                             DES2, soft_des_ctx->key_sched);
 143                 else
 144                         des_init_keysched(OBJ_SEC(key_p)->sk_value,
 145                             DES3, soft_des_ctx->key_sched);
 146         }
 147 
 148         return (CKR_OK);
 149 }
 150 
 151 
 152 /*
 153  * soft_des_encrypt_common()
 154  *
 155  * Arguments:
 156  *      session_p:      pointer to soft_session_t struct
 157  *      pData:          pointer to the input data to be encrypted
 158  *      ulDataLen:      length of the input data
 159  *      pEncrypted:     pointer to the output data after encryption
 160  *      pulEncryptedLen: pointer to the length of the output data
 161  *      update:         boolean flag indicates caller is soft_encrypt
 162  *                      or soft_encrypt_update
 163  *
 164  * Description:
 165  *      This function calls the corresponding encrypt routine based
 166  *      on the mechanism.
 167  *
 168  * Returns:
 169  *      CKR_OK: success
 170  *      CKR_BUFFER_TOO_SMALL: the output buffer provided by application
 171  *                            is too small
 172  *      CKR_FUNCTION_FAILED: encrypt function failed
 173  *      CKR_DATA_LEN_RANGE: the input data is not a multiple of blocksize
 174  */
 175 CK_RV
 176 soft_des_encrypt_common(soft_session_t *session_p, CK_BYTE_PTR pData,
 177     CK_ULONG ulDataLen, CK_BYTE_PTR pEncrypted,
 178     CK_ULONG_PTR pulEncryptedLen, boolean_t update)
 179 {
 180         int rc = 0;
 181         CK_RV rv = CKR_OK;
 182         soft_des_ctx_t *soft_des_ctx =
 183             (soft_des_ctx_t *)session_p->encrypt.context;
 184         des_ctx_t *des_ctx;
 185         CK_MECHANISM_TYPE mechanism = session_p->encrypt.mech.mechanism;
 186         CK_BYTE *in_buf = NULL;
 187         CK_BYTE *out_buf = NULL;
 188         CK_ULONG out_len;
 189         CK_ULONG total_len;
 190         CK_ULONG remain;
 191         boolean_t pad_mechanism = B_FALSE;
 192 
 193         pad_mechanism = (mechanism == CKM_DES_CBC_PAD ||
 194             mechanism == CKM_DES3_CBC_PAD);
 195         /*
 196          * DES only takes input length that is a multiple of blocksize
 197          * for C_Encrypt function with the mechanism CKM_DES<n>_ECB or
 198          * CKM_DES<n>_CBC.
 199          *
 200          * DES allows any input length for C_Encrypt function with the
 201          * mechanism CKM_DES<n>_CBC_PAD and for C_EncryptUpdate function.
 202          */
 203         if (!update && !pad_mechanism) {
 204                 if ((ulDataLen % DES_BLOCK_LEN) != 0) {
 205                         rv = CKR_DATA_LEN_RANGE;
 206                         goto cleanup;
 207                 }
 208         }
 209 
 210         if (!update) {
 211                 /*
 212                  * Called by C_Encrypt
 213                  */
 214                 if (pad_mechanism) {
 215                         /*
 216                          * For CKM_DES<n>_CBC_PAD, compute output length to
 217                          * count for the padding. If the length of input
 218                          * data is a multiple of blocksize, then make output
 219                          * length to be the sum of the input length and
 220                          * one blocksize. Otherwise, output length will
 221                          * be rounded up to the next multiple of blocksize.
 222                          */
 223                         out_len = DES_BLOCK_LEN *
 224                             (ulDataLen / DES_BLOCK_LEN + 1);
 225                 } else {
 226                         /*
 227                          * For non-padding mode, the output length will
 228                          * be same as the input length.
 229                          */
 230                         out_len = ulDataLen;
 231                 }
 232 
 233                 /*
 234                  * If application asks for the length of the output buffer
 235                  * to hold the ciphertext?
 236                  */
 237                 if (pEncrypted == NULL) {
 238                         *pulEncryptedLen = out_len;
 239                         return (CKR_OK);
 240                 }
 241 
 242                 /* Is the application-supplied buffer large enough? */
 243                 if (*pulEncryptedLen < out_len) {
 244                         *pulEncryptedLen = out_len;
 245                         return (CKR_BUFFER_TOO_SMALL);
 246                 }
 247 
 248                 /* Encrypt pad bytes in a separate operation */
 249                 if (pad_mechanism) {
 250                         out_len -= DES_BLOCK_LEN;
 251                 }
 252 
 253                 in_buf = pData;
 254                 out_buf = pEncrypted;
 255         } else {
 256                 /*
 257                  * Called by C_EncryptUpdate
 258                  *
 259                  * Add the lengths of last remaining data and current
 260                  * plaintext together to get the total input length.
 261                  */
 262                 total_len = soft_des_ctx->remain_len + ulDataLen;
 263 
 264                 /*
 265                  * If the total input length is less than one blocksize,
 266                  * or if the total input length is just one blocksize and
 267                  * the mechanism is CKM_DES<n>_CBC_PAD, we will need to delay
 268                  * encryption until when more data comes in next
 269                  * C_EncryptUpdate or when C_EncryptFinal is called.
 270                  */
 271                 if ((total_len < DES_BLOCK_LEN) ||
 272                     (pad_mechanism && (total_len == DES_BLOCK_LEN))) {
 273                         if (pData != NULL) {
 274                                 /*
 275                                  * Save input data and its length in
 276                                  * the remaining buffer of DES context.
 277                                  */
 278                                 (void) memcpy(soft_des_ctx->data +
 279                                     soft_des_ctx->remain_len, pData, ulDataLen);
 280                                 soft_des_ctx->remain_len += ulDataLen;
 281                         }
 282 
 283                         /* Set encrypted data length to 0. */
 284                         *pulEncryptedLen = 0;
 285                         return (CKR_OK);
 286                 }
 287 
 288                 /* Compute the length of remaing data. */
 289                 remain = total_len % DES_BLOCK_LEN;
 290 
 291                 /*
 292                  * Make sure that the output length is a multiple of
 293                  * blocksize.
 294                  */
 295                 out_len = total_len - remain;
 296 
 297                 /*
 298                  * If application asks for the length of the output buffer
 299                  * to hold the ciphertext?
 300                  */
 301                 if (pEncrypted == NULL) {
 302                         *pulEncryptedLen = out_len;
 303                         return (CKR_OK);
 304                 }
 305 
 306                 /* Is the application-supplied buffer large enough? */
 307                 if (*pulEncryptedLen < out_len) {
 308                         *pulEncryptedLen = out_len;
 309                         return (CKR_BUFFER_TOO_SMALL);
 310                 }
 311 
 312                 if (soft_des_ctx->remain_len != 0) {
 313                         /*
 314                          * Copy last remaining data and current input data
 315                          * to the output buffer.
 316                          */
 317                         (void) memmove(pEncrypted + soft_des_ctx->remain_len,
 318                             pData, out_len - soft_des_ctx->remain_len);
 319                         (void) memcpy(pEncrypted, soft_des_ctx->data,
 320                             soft_des_ctx->remain_len);
 321                         bzero(soft_des_ctx->data, soft_des_ctx->remain_len);
 322 
 323                         in_buf = pEncrypted;
 324                 } else {
 325                         in_buf = pData;
 326                 }
 327                 out_buf = pEncrypted;
 328         }
 329 
 330         /*
 331          * Begin Encryption now.
 332          */
 333         switch (mechanism) {
 334 
 335         case CKM_DES_ECB:
 336         case CKM_DES3_ECB:
 337         {
 338 
 339                 ulong_t i;
 340                 uint8_t *tmp_inbuf;
 341                 uint8_t *tmp_outbuf;
 342 
 343                 for (i = 0; i < out_len; i += DES_BLOCK_LEN) {
 344                         tmp_inbuf = &in_buf[i];
 345                         tmp_outbuf = &out_buf[i];
 346                         /* Crunch one block of data for DES. */
 347                         if (soft_des_ctx->key_type == CKK_DES)
 348                                 (void) des_crunch_block(
 349                                     soft_des_ctx->key_sched,
 350                                     tmp_inbuf, tmp_outbuf, B_FALSE);
 351                         else
 352                                 (void) des3_crunch_block(
 353                                     soft_des_ctx->key_sched,
 354                                     tmp_inbuf, tmp_outbuf, B_FALSE);
 355                 }
 356 
 357                 if (update) {
 358                         /*
 359                          * For encrypt update, if there is remaining
 360                          * data, save it and its length in the context.
 361                          */
 362                         if (remain != 0)
 363                                 (void) memcpy(soft_des_ctx->data, pData +
 364                                     (ulDataLen - remain), remain);
 365                         soft_des_ctx->remain_len = remain;
 366                 }
 367 
 368                 *pulEncryptedLen = out_len;
 369                 break;
 370         }
 371 
 372         case CKM_DES_CBC:
 373         case CKM_DES_CBC_PAD:
 374         case CKM_DES3_CBC:
 375         case CKM_DES3_CBC_PAD:
 376         {
 377                 crypto_data_t out;
 378 
 379                 out.cd_format =  CRYPTO_DATA_RAW;
 380                 out.cd_offset = 0;
 381                 out.cd_length = out_len;
 382                 out.cd_raw.iov_base = (char *)out_buf;
 383                 out.cd_raw.iov_len = out_len;
 384 
 385                 /* Encrypt multiple blocks of data. */
 386                 rc = des_encrypt_contiguous_blocks(
 387                     (des_ctx_t *)soft_des_ctx->des_cbc,
 388                     (char *)in_buf, out_len, &out);
 389 
 390                 if (rc != 0)
 391                         goto encrypt_failed;
 392 
 393                 if (update) {
 394                         /*
 395                          * For encrypt update, if there is remaining data,
 396                          * save it and its length in the context.
 397                          */
 398                         if (remain != 0)
 399                                 (void) memcpy(soft_des_ctx->data, pData +
 400                                     (ulDataLen - remain), remain);
 401                         soft_des_ctx->remain_len = remain;
 402                 } else if (pad_mechanism) {
 403                         /*
 404                          * Save the remainder of the input
 405                          * block in a temporary block because
 406                          * we don't want to overrun the input buffer
 407                          * by tacking on pad bytes.
 408                          */
 409                         CK_BYTE tmpblock[DES_BLOCK_LEN];
 410                         (void) memcpy(tmpblock, in_buf + out_len,
 411                             ulDataLen - out_len);
 412                         soft_add_pkcs7_padding(tmpblock +
 413                             (ulDataLen - out_len),
 414                             DES_BLOCK_LEN, ulDataLen - out_len);
 415 
 416                         out.cd_offset = out_len;
 417                         out.cd_length = DES_BLOCK_LEN;
 418                         out.cd_raw.iov_base = (char *)out_buf;
 419                         out.cd_raw.iov_len = out_len + DES_BLOCK_LEN;
 420 
 421                         /* Encrypt last block containing pad bytes. */
 422                         rc = des_encrypt_contiguous_blocks(
 423                             (des_ctx_t *)soft_des_ctx->des_cbc,
 424                             (char *)tmpblock, DES_BLOCK_LEN, &out);
 425                         out_len += DES_BLOCK_LEN;
 426                 }
 427 
 428                 if (rc == 0) {
 429                         *pulEncryptedLen = out_len;
 430                         break;
 431                 }
 432 encrypt_failed:
 433                 *pulEncryptedLen = 0;
 434                 rv = CKR_FUNCTION_FAILED;
 435                 goto cleanup;
 436 
 437         }
 438         } /* end switch */
 439 
 440         if (update)
 441                 return (CKR_OK);
 442 
 443         /*
 444          * The following code will be executed if the caller is
 445          * soft_encrypt() or an error occurred. The encryption
 446          * operation will be terminated so we need to do some cleanup.
 447          */
 448 cleanup:
 449         (void) pthread_mutex_lock(&session_p->session_mutex);
 450         des_ctx = (des_ctx_t *)soft_des_ctx->des_cbc;
 451         if (des_ctx != NULL) {
 452                 bzero(des_ctx->dc_keysched, des_ctx->dc_keysched_len);
 453                 free(soft_des_ctx->des_cbc);
 454         }
 455 
 456         bzero(soft_des_ctx->key_sched, soft_des_ctx->keysched_len);
 457         free(soft_des_ctx->key_sched);
 458         free(session_p->encrypt.context);
 459         session_p->encrypt.context = NULL;
 460         (void) pthread_mutex_unlock(&session_p->session_mutex);
 461 
 462         return (rv);
 463 }
 464 
 465 
 466 /*
 467  * soft_des_decrypt_common()
 468  *
 469  * Arguments:
 470  *      session_p:      pointer to soft_session_t struct
 471  *      pEncrypted:     pointer to the input data to be decrypted
 472  *      ulEncryptedLen: length of the input data
 473  *      pData:          pointer to the output data
 474  *      pulDataLen:     pointer to the length of the output data
 475  *      Update:         boolean flag indicates caller is soft_decrypt
 476  *                      or soft_decrypt_update
 477  *
 478  * Description:
 479  *      This function calls the corresponding decrypt routine based
 480  *      on the mechanism.
 481  *
 482  * Returns:
 483  *      CKR_OK: success
 484  *      CKR_BUFFER_TOO_SMALL: the output buffer provided by application
 485  *                            is too small
 486  *      CKR_ENCRYPTED_DATA_LEN_RANGE: the input data is not a multiple
 487  *                                    of blocksize
 488  *      CKR_FUNCTION_FAILED: decrypt function failed
 489  */
 490 CK_RV
 491 soft_des_decrypt_common(soft_session_t *session_p, CK_BYTE_PTR pEncrypted,
 492     CK_ULONG ulEncryptedLen, CK_BYTE_PTR pData,
 493     CK_ULONG_PTR pulDataLen, boolean_t update)
 494 {
 495 
 496         int rc = 0;
 497         CK_RV rv = CKR_OK;
 498         soft_des_ctx_t *soft_des_ctx =
 499             (soft_des_ctx_t *)session_p->decrypt.context;
 500         des_ctx_t *des_ctx;
 501         CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
 502         CK_BYTE *in_buf = NULL;
 503         CK_BYTE *out_buf = NULL;
 504         CK_ULONG out_len;
 505         CK_ULONG total_len;
 506         CK_ULONG remain;
 507         boolean_t pad_mechanism = B_FALSE;
 508 
 509         pad_mechanism = (mechanism == CKM_DES_CBC_PAD ||
 510             mechanism == CKM_DES3_CBC_PAD);
 511         /*
 512          * DES only takes input length that is a multiple of 8 bytes
 513          * for C_Decrypt function with the mechanism CKM_DES<n>_ECB,
 514          * CKM_DES<n>_CBC or CKM_DES<n>_CBC_PAD.
 515          *
 516          * DES allows any input length for C_DecryptUpdate function.
 517          */
 518         if (!update) {
 519                 /*
 520                  * Called by C_Decrypt
 521                  */
 522                 if ((ulEncryptedLen % DES_BLOCK_LEN) != 0) {
 523                         rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
 524                         goto cleanup;
 525                 }
 526 
 527                 /*
 528                  * If application asks for the length of the output buffer
 529                  * to hold the plaintext?
 530                  */
 531                 if (pData == NULL) {
 532                         *pulDataLen = ulEncryptedLen;
 533                         return (CKR_OK);
 534                 }
 535 
 536                 /* Is the application-supplied buffer large enough? */
 537                 if (!pad_mechanism) {
 538                         if (*pulDataLen < ulEncryptedLen) {
 539                                 *pulDataLen = ulEncryptedLen;
 540                                 return (CKR_BUFFER_TOO_SMALL);
 541                         }
 542 
 543                         /* Set output length same as input length. */
 544                         out_len = ulEncryptedLen;
 545                 } else {
 546                         /*
 547                          * For CKM_DES<n>_CBC_PAD, we don't know how
 548                          * many bytes for padding at this time, so
 549                          * we'd assume one block was padded.
 550                          */
 551                         if (*pulDataLen < (ulEncryptedLen - DES_BLOCK_LEN)) {
 552                                 *pulDataLen = ulEncryptedLen - DES_BLOCK_LEN;
 553                                 return (CKR_BUFFER_TOO_SMALL);
 554                         }
 555                         out_len = ulEncryptedLen - DES_BLOCK_LEN;
 556                 }
 557                 in_buf = pEncrypted;
 558                 out_buf = pData;
 559         } else {
 560                 /*
 561                  *  Called by C_DecryptUpdate
 562                  *
 563                  * Add the lengths of last remaining data and current
 564                  * input data together to get the total input length.
 565                  */
 566                 total_len = soft_des_ctx->remain_len + ulEncryptedLen;
 567 
 568                 /*
 569                  * If the total input length is less than one blocksize,
 570                  * or if the total input length is just one blocksize and
 571                  * the mechanism is CKM_DES<n>_CBC_PAD, we will need to delay
 572                  * decryption until when more data comes in next
 573                  * C_DecryptUpdate or when C_DecryptFinal is called.
 574                  */
 575                 if ((total_len < DES_BLOCK_LEN) ||
 576                     (pad_mechanism && (total_len == DES_BLOCK_LEN))) {
 577                         if (pEncrypted != NULL) {
 578                                 /*
 579                                  * Save input data and its length in
 580                                  * the remaining buffer of DES context.
 581                                  */
 582                                 (void) memcpy(soft_des_ctx->data +
 583                                     soft_des_ctx->remain_len,
 584                                     pEncrypted, ulEncryptedLen);
 585                                 soft_des_ctx->remain_len += ulEncryptedLen;
 586                         }
 587 
 588                         /* Set output data length to 0. */
 589                         *pulDataLen = 0;
 590                         return (CKR_OK);
 591                 }
 592 
 593                 /* Compute the length of remaing data. */
 594                 remain = total_len % DES_BLOCK_LEN;
 595 
 596                 /*
 597                  * Make sure that the output length is a multiple of
 598                  * blocksize.
 599                  */
 600                 out_len = total_len - remain;
 601 
 602                 if (pad_mechanism) {
 603                         /*
 604                          * If the input data length is a multiple of
 605                          * blocksize, then save the last block of input
 606                          * data in the remaining buffer. C_DecryptFinal
 607                          * will handle this last block of data.
 608                          */
 609                         if (remain == 0) {
 610                                 remain = DES_BLOCK_LEN;
 611                                 out_len -= DES_BLOCK_LEN;
 612                         }
 613                 }
 614 
 615                 /*
 616                  * If application asks for the length of the output buffer
 617                  * to hold the plaintext?
 618                  */
 619                 if (pData == NULL) {
 620                         *pulDataLen = out_len;
 621                         return (CKR_OK);
 622                 }
 623 
 624                 /*
 625                  * Is the application-supplied buffer large enough?
 626                  */
 627                 if (*pulDataLen < out_len) {
 628                         *pulDataLen = out_len;
 629                         return (CKR_BUFFER_TOO_SMALL);
 630                 }
 631 
 632                 if (soft_des_ctx->remain_len != 0) {
 633                         /*
 634                          * Copy last remaining data and current input data
 635                          * to the output buffer.
 636                          */
 637                         (void) memmove(pData + soft_des_ctx->remain_len,
 638                             pEncrypted, out_len - soft_des_ctx->remain_len);
 639                         (void) memcpy(pData, soft_des_ctx->data,
 640                             soft_des_ctx->remain_len);
 641                         bzero(soft_des_ctx->data, soft_des_ctx->remain_len);
 642 
 643                         in_buf = pData;
 644                 } else {
 645                         in_buf = pEncrypted;
 646                 }
 647                 out_buf = pData;
 648         }
 649 
 650         /*
 651          * Begin Decryption.
 652          */
 653         switch (mechanism) {
 654 
 655         case CKM_DES_ECB:
 656         case CKM_DES3_ECB:
 657         {
 658                 uint8_t *tmp_inbuf;
 659                 uint8_t *tmp_outbuf;
 660                 ulong_t i;
 661 
 662                 for (i = 0; i < out_len; i += DES_BLOCK_LEN) {
 663                         tmp_inbuf = &in_buf[i];
 664                         tmp_outbuf = &out_buf[i];
 665                         /* Crunch one block of data for DES. */
 666                         if (soft_des_ctx->key_type == CKK_DES)
 667                                 (void) des_crunch_block(
 668                                     soft_des_ctx->key_sched,
 669                                     tmp_inbuf, tmp_outbuf, B_TRUE);
 670                         else
 671                                 (void) des3_crunch_block(
 672                                     soft_des_ctx->key_sched,
 673                                     tmp_inbuf, tmp_outbuf, B_TRUE);
 674                 }
 675 
 676                 if (update) {
 677                         /*
 678                          * For decrypt update, if there is remaining
 679                          * data, save it and its length in the context.
 680                          */
 681                         if (remain != 0)
 682                                 (void) memcpy(soft_des_ctx->data, pEncrypted +
 683                                     (ulEncryptedLen - remain), remain);
 684                         soft_des_ctx->remain_len = remain;
 685                 }
 686 
 687                 *pulDataLen = out_len;
 688                 break;
 689         }
 690 
 691         case CKM_DES_CBC:
 692         case CKM_DES_CBC_PAD:
 693         case CKM_DES3_CBC:
 694         case CKM_DES3_CBC_PAD:
 695         {
 696                 crypto_data_t out;
 697                 CK_ULONG rem_len;
 698                 uint8_t last_block[DES_BLOCK_LEN];
 699 
 700                 out.cd_format =  CRYPTO_DATA_RAW;
 701                 out.cd_offset = 0;
 702                 out.cd_length = out_len;
 703                 out.cd_raw.iov_base = (char *)out_buf;
 704                 out.cd_raw.iov_len = out_len;
 705 
 706                 /* Decrypt multiple blocks of data. */
 707                 rc = des_decrypt_contiguous_blocks(
 708                     (des_ctx_t *)soft_des_ctx->des_cbc,
 709                     (char *)in_buf, out_len, &out);
 710 
 711                 if (rc != 0)
 712                         goto decrypt_failed;
 713 
 714                 if (pad_mechanism && !update) {
 715                         /* Decrypt last block containing pad bytes. */
 716                         out.cd_offset = 0;
 717                         out.cd_length = DES_BLOCK_LEN;
 718                         out.cd_raw.iov_base = (char *)last_block;
 719                         out.cd_raw.iov_len = DES_BLOCK_LEN;
 720 
 721                         /* Decrypt last block containing pad bytes. */
 722                         rc = des_decrypt_contiguous_blocks(
 723                             (des_ctx_t *)soft_des_ctx->des_cbc,
 724                             (char *)in_buf + out_len, DES_BLOCK_LEN, &out);
 725 
 726                         if (rc != 0)
 727                                 goto decrypt_failed;
 728 
 729                         /*
 730                          * Remove padding bytes after decryption of
 731                          * ciphertext block to produce the original
 732                          * plaintext.
 733                          */
 734                         rv = soft_remove_pkcs7_padding(last_block,
 735                             DES_BLOCK_LEN, &rem_len);
 736                         if (rv == CKR_OK) {
 737                                 if (rem_len != 0)
 738                                         (void) memcpy(out_buf + out_len,
 739                                             last_block, rem_len);
 740                                 *pulDataLen = out_len + rem_len;
 741                         } else {
 742                                 *pulDataLen = 0;
 743                                 goto cleanup;
 744                         }
 745                 } else {
 746                         *pulDataLen = out_len;
 747                 }
 748 
 749                 if (update) {
 750                         /*
 751                          * For decrypt update, if there is remaining data,
 752                          * save it and its length in the context.
 753                          */
 754                         if (remain != 0)
 755                                 (void) memcpy(soft_des_ctx->data, pEncrypted +
 756                                     (ulEncryptedLen - remain), remain);
 757                         soft_des_ctx->remain_len = remain;
 758                 }
 759 
 760                 if (rc == 0)
 761                         break;
 762 decrypt_failed:
 763                 *pulDataLen = 0;
 764                 rv = CKR_FUNCTION_FAILED;
 765                 goto cleanup;
 766         }
 767         } /* end switch */
 768 
 769         if (update)
 770                 return (CKR_OK);
 771 
 772         /*
 773          * The following code will be executed if the caller is
 774          * soft_decrypt() or an error occurred. The decryption
 775          * operation will be terminated so we need to do some cleanup.
 776          */
 777 cleanup:
 778         (void) pthread_mutex_lock(&session_p->session_mutex);
 779         des_ctx = (des_ctx_t *)soft_des_ctx->des_cbc;
 780         if (des_ctx != NULL) {
 781                 bzero(des_ctx->dc_keysched, des_ctx->dc_keysched_len);
 782                 free(soft_des_ctx->des_cbc);
 783         }
 784 
 785         bzero(soft_des_ctx->key_sched, soft_des_ctx->keysched_len);
 786         free(soft_des_ctx->key_sched);
 787         free(session_p->decrypt.context);
 788         session_p->decrypt.context = NULL;
 789         (void) pthread_mutex_unlock(&session_p->session_mutex);
 790 
 791         return (rv);
 792 }
 793 
 794 
 795 /*
 796  * Allocate and initialize a context for DES CBC mode of operation.
 797  */
 798 void *
 799 des_cbc_ctx_init(void *key_sched, size_t size, uint8_t *ivec, CK_KEY_TYPE type)
 800 {
 801 
 802         cbc_ctx_t *cbc_ctx;
 803 
 804         if ((cbc_ctx = calloc(1, sizeof (cbc_ctx_t))) == NULL)
 805                 return (NULL);
 806 
 807         cbc_ctx->cbc_keysched = key_sched;
 808 
 809         (void) memcpy(&cbc_ctx->cbc_iv[0], ivec, DES_BLOCK_LEN);
 810 
 811         cbc_ctx->cbc_lastp = (uint8_t *)&cbc_ctx->cbc_iv[0];
 812         cbc_ctx->cbc_keysched_len = size;
 813         if (type == CKK_DES)
 814                 cbc_ctx->cbc_flags |= CBC_MODE;
 815         else
 816                 cbc_ctx->cbc_flags |= CBC_MODE | DES3_STRENGTH;
 817 
 818         return (cbc_ctx);
 819 
 820 }
 821 
 822 /*
 823  * Allocate and initialize DES contexts for both signing and encrypting,
 824  * saving both context pointers in the session struct. For general-length DES
 825  * MAC, check the length in the parameter to see if it is in the right range.
 826  */
 827 CK_RV
 828 soft_des_sign_verify_init_common(soft_session_t *session_p,
 829         CK_MECHANISM_PTR pMechanism, soft_object_t *key_p, boolean_t sign_op)
 830 {
 831         soft_des_ctx_t  *soft_des_ctx;
 832         CK_MECHANISM    encrypt_mech;
 833         CK_RV rv;
 834 
 835         if ((key_p->class != CKO_SECRET_KEY) || (key_p->key_type != CKK_DES)) {
 836                 return (CKR_KEY_TYPE_INCONSISTENT);
 837         }
 838 
 839         /* allocate memory for the sign/verify context */
 840         soft_des_ctx = malloc(sizeof (soft_des_ctx_t));
 841         if (soft_des_ctx == NULL) {
 842                 return (CKR_HOST_MEMORY);
 843         }
 844 
 845         soft_des_ctx->key_type = key_p->key_type;
 846 
 847         /* initialization vector is zero for DES MAC */
 848         bzero(soft_des_ctx->ivec, DES_BLOCK_LEN);
 849 
 850         switch (pMechanism->mechanism) {
 851 
 852         case CKM_DES_MAC_GENERAL:
 853 
 854                 if (pMechanism->ulParameterLen !=
 855                     sizeof (CK_MAC_GENERAL_PARAMS)) {
 856                         free(soft_des_ctx);
 857                         return (CKR_MECHANISM_PARAM_INVALID);
 858                 }
 859 
 860                 if (*(CK_MAC_GENERAL_PARAMS *)pMechanism->pParameter >
 861                     DES_BLOCK_LEN) {
 862                         free(soft_des_ctx);
 863                         return (CKR_MECHANISM_PARAM_INVALID);
 864                 }
 865 
 866                 soft_des_ctx->mac_len = *((CK_MAC_GENERAL_PARAMS_PTR)
 867                     pMechanism->pParameter);
 868 
 869                 /*FALLTHRU*/
 870         case CKM_DES_MAC:
 871 
 872                 /*
 873                  * For non-general DES MAC, output is always half as
 874                  * large as block size
 875                  */
 876                 if (pMechanism->mechanism == CKM_DES_MAC) {
 877                         soft_des_ctx->mac_len = DES_MAC_LEN;
 878                 }
 879 
 880                 /* allocate a context for DES encryption */
 881                 encrypt_mech.mechanism = CKM_DES_CBC_PAD;
 882                 encrypt_mech.pParameter = (void *)soft_des_ctx->ivec;
 883                 encrypt_mech.ulParameterLen = DES_BLOCK_LEN;
 884                 rv = soft_encrypt_init_internal(session_p, &encrypt_mech,
 885                     key_p);
 886                 if (rv != CKR_OK) {
 887                         free(soft_des_ctx);
 888                         return (rv);
 889                 }
 890 
 891                 (void) pthread_mutex_lock(&session_p->session_mutex);
 892 
 893                 if (sign_op) {
 894                         session_p->sign.context = soft_des_ctx;
 895                         session_p->sign.mech.mechanism = pMechanism->mechanism;
 896                 } else {
 897                         session_p->verify.context = soft_des_ctx;
 898                         session_p->verify.mech.mechanism =
 899                             pMechanism->mechanism;
 900                 }
 901 
 902                 (void) pthread_mutex_unlock(&session_p->session_mutex);
 903 
 904                 break;
 905         }
 906         return (CKR_OK);
 907 }
 908 
 909 /*
 910  * Called by soft_sign(), soft_sign_final(), soft_verify() or
 911  * soft_verify_final().
 912  */
 913 CK_RV
 914 soft_des_sign_verify_common(soft_session_t *session_p, CK_BYTE_PTR pData,
 915         CK_ULONG ulDataLen, CK_BYTE_PTR pSigned, CK_ULONG_PTR pulSignedLen,
 916         boolean_t sign_op, boolean_t Final)
 917 {
 918         soft_des_ctx_t          *soft_des_ctx_sign_verify;
 919         soft_des_ctx_t          *soft_des_ctx_encrypt;
 920         CK_RV                   rv;
 921         CK_BYTE                 *pEncrypted = NULL;
 922         CK_ULONG                ulEncryptedLen = 0;
 923         uint8_t                 remainder;
 924         CK_BYTE                 last_block[DES_BLOCK_LEN];
 925         des_ctx_t               *des_ctx = NULL;
 926 
 927         if (sign_op) {
 928                 soft_des_ctx_sign_verify =
 929                     (soft_des_ctx_t *)session_p->sign.context;
 930 
 931                 if (soft_des_ctx_sign_verify->mac_len == 0) {
 932                         *pulSignedLen = 0;
 933                         goto clean_exit;
 934                 }
 935 
 936                 /* Application asks for the length of the output buffer. */
 937                 if (pSigned == NULL) {
 938                         *pulSignedLen = soft_des_ctx_sign_verify->mac_len;
 939                         return (CKR_OK);
 940                 }
 941 
 942                 /* Is the application-supplied buffer large enough? */
 943                 if (*pulSignedLen < soft_des_ctx_sign_verify->mac_len) {
 944                         *pulSignedLen = soft_des_ctx_sign_verify->mac_len;
 945                         return (CKR_BUFFER_TOO_SMALL);
 946                 }
 947         } else {
 948                 soft_des_ctx_sign_verify =
 949                     (soft_des_ctx_t *)session_p->verify.context;
 950         }
 951 
 952         if (Final) {
 953                 soft_des_ctx_encrypt =
 954                     (soft_des_ctx_t *)session_p->encrypt.context;
 955 
 956                 /*
 957                  * If there is data left in the buffer from a previous
 958                  * SignUpdate() call, pass enough zeroed data to a
 959                  * soft_sign_update call to pad the remainder
 960                  */
 961                 if (soft_des_ctx_encrypt->remain_len != 0) {
 962                         bzero(last_block, DES_BLOCK_LEN);
 963                         ulEncryptedLen = DES_BLOCK_LEN;
 964 
 965                         /*
 966                          * By passing a buffer to soft_encrypt_final,
 967                          * we force it to pad the remaining block
 968                          * and encrypt it.
 969                          */
 970                         rv = soft_encrypt_final(session_p, last_block,
 971                             &ulEncryptedLen);
 972                         if (rv != CKR_OK) {
 973                                 goto clean_exit;
 974                         }
 975                 } else {
 976                         /*
 977                          * The last block of enciphered data is stored in:
 978                          * soft_des_ctx_encrypt->des_cbc->des_ctx->dc_lastp
 979                          * Copy that data to last_block
 980                          */
 981                         soft_des_ctx_encrypt =
 982                             (soft_des_ctx_t *)session_p->encrypt.context;
 983                         des_ctx = (des_ctx_t *)soft_des_ctx_encrypt->des_cbc;
 984                         (void) memcpy(last_block, des_ctx->dc_lastp,
 985                             DES_BLOCK_LEN);
 986 
 987                         /*
 988                          * Passing a NULL output buffer here
 989                          * forces the routine to just return.
 990                          */
 991                         rv = soft_encrypt_final(session_p, NULL,
 992                             &ulEncryptedLen);
 993                 }
 994 
 995         } else {
 996                 /*
 997                  * If the input length is not multiple of block size, then
 998                  * determine the correct encrypted data length by rounding
 999                  */
1000                 remainder = ulDataLen % DES_BLOCK_LEN;
1001                 /*
1002                  * Because we always use DES_CBC_PAD mechanism
1003                  * for sign/verify operations, the input will
1004                  * be padded to the next 8 byte boundary.
1005                  * Adjust the length fields here accordingly.
1006                  */
1007                 ulEncryptedLen = ulDataLen + (DES_BLOCK_LEN - remainder);
1008 
1009                 pEncrypted = malloc(sizeof (CK_BYTE) * ulEncryptedLen);
1010                 if (pEncrypted == NULL) {
1011                         rv = CKR_HOST_MEMORY;
1012                         goto clean_exit;
1013                 }
1014 
1015                 /*
1016                  * Pad the last block with zeros by copying pData into a zeroed
1017                  * pEncrypted. Then pass pEncrypted into soft_encrypt as input
1018                  */
1019                 bzero(pEncrypted, ulEncryptedLen);
1020                 (void) memcpy(pEncrypted, pData, ulDataLen);
1021 
1022                 rv = soft_encrypt(session_p, pEncrypted, ulDataLen,
1023                     pEncrypted, &ulEncryptedLen);
1024                 (void) memcpy(last_block,
1025                     &pEncrypted[ulEncryptedLen - DES_BLOCK_LEN], DES_BLOCK_LEN);
1026         }
1027 
1028         if (rv == CKR_OK) {
1029                 *pulSignedLen = soft_des_ctx_sign_verify->mac_len;
1030 
1031                 /* the leftmost mac_len bytes of last_block is our MAC */
1032                 (void) memcpy(pSigned, last_block, *pulSignedLen);
1033         }
1034 
1035 clean_exit:
1036 
1037         (void) pthread_mutex_lock(&session_p->session_mutex);
1038 
1039         /* soft_encrypt_common() has freed the encrypt context */
1040         if (sign_op) {
1041                 free(session_p->sign.context);
1042                 session_p->sign.context = NULL;
1043         } else {
1044                 free(session_p->verify.context);
1045                 session_p->verify.context = NULL;
1046         }
1047         session_p->encrypt.flags = 0;
1048 
1049         (void) pthread_mutex_unlock(&session_p->session_mutex);
1050 
1051         if (pEncrypted) {
1052                 free(pEncrypted);
1053         }
1054 
1055         return (rv);
1056 }
1057 
1058 /*
1059  * Called by soft_sign_update()
1060  */
1061 CK_RV
1062 soft_des_mac_sign_verify_update(soft_session_t *session_p, CK_BYTE_PTR pPart,
1063         CK_ULONG ulPartLen)
1064 {
1065         /*
1066          * The DES MAC is calculated by taking the specified number of
1067          * left-most bytes within the last block of
1068          * encrypted data, while the context of the multi-part
1069          * encryption stores the block necessary for XORing with the
1070          * input as per cipher block chaining . Therefore, none of the
1071          * intermediary encrypted blocks of data are necessary for
1072          * the DES MAC, and we can create a placeholder local buffer
1073          * for the encrypted data, which is immediately throw away.
1074          */
1075 
1076         soft_des_ctx_t  *soft_des_ctx_encrypt;
1077         CK_BYTE         *pEncrypted = NULL;
1078         CK_ULONG        ulEncryptedLen;
1079         CK_ULONG        total_len;
1080         uint8_t         remainder;
1081         CK_RV           rv;
1082 
1083         soft_des_ctx_encrypt = (soft_des_ctx_t *)session_p->encrypt.context;
1084 
1085         /* Avoid the malloc if we won't be encrypting any data */
1086         total_len = soft_des_ctx_encrypt->remain_len + ulPartLen;
1087 
1088         if (total_len < DES_BLOCK_LEN) {
1089                 rv = soft_encrypt_update(session_p, pPart, ulPartLen, NULL,
1090                     &ulEncryptedLen);
1091         } else {
1092                 remainder = ulPartLen % DES_BLOCK_LEN;
1093 
1094                 /* round up to the nearest multiple of block size */
1095                 ulEncryptedLen = ulPartLen + (DES_BLOCK_LEN - remainder);
1096                 pEncrypted = malloc(sizeof (CK_BYTE) * ulEncryptedLen);
1097 
1098                 if (pEncrypted != NULL) {
1099                         rv = soft_encrypt_update(session_p, pPart, ulPartLen,
1100                             pEncrypted, &ulEncryptedLen);
1101                         free(pEncrypted);
1102                 } else {
1103                         rv = CKR_HOST_MEMORY;
1104                 }
1105         }
1106         return (rv);
1107 }