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