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