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 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 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_cbc_crypt.h> 35 #include <aes_impl.h> 36 #include "softSession.h" 37 #include "softObject.h" 38 #include "softCrypt.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 /* 175 * AES only takes input length that is a multiple of blocksize 176 * for C_Encrypt function with the mechanism CKM_AES_ECB or 177 * CKM_AES_CBC. 178 * 179 * AES allows any input length for C_Encrypt function with the 180 * mechanism CKM_AES_CBC_PAD and for C_EncryptUpdate function. 181 */ 182 if ((!update) && (mechanism != CKM_AES_CBC_PAD)) { 183 if ((ulDataLen % AES_BLOCK_LEN) != 0) { 184 rv = CKR_DATA_LEN_RANGE; 185 goto cleanup; 186 } 187 } 188 189 if (!update) { 190 /* 191 * Called by C_Encrypt 192 */ 193 if (mechanism == CKM_AES_CBC_PAD) { 194 /* 195 * For CKM_AES_CBC_PAD, compute output length to 196 * count for the padding. If the length of input 197 * data is a multiple of blocksize, then make output 198 * length to be the sum of the input length and 199 * one blocksize. Otherwise, output length will 200 * be rounded up to the next multiple of blocksize. 201 */ 202 out_len = AES_BLOCK_LEN * 203 (ulDataLen / AES_BLOCK_LEN + 1); 204 } else { 205 /* 206 * For non-padding mode, the output length will 207 * be same as the input length. 208 */ 209 out_len = ulDataLen; 210 } 211 212 /* 213 * If application asks for the length of the output buffer 214 * to hold the ciphertext? 215 */ 216 if (pEncrypted == NULL) { 217 *pulEncryptedLen = out_len; 218 return (CKR_OK); 219 } 220 221 /* Is the application-supplied buffer large enough? */ 222 if (*pulEncryptedLen < out_len) { 223 *pulEncryptedLen = out_len; 224 return (CKR_BUFFER_TOO_SMALL); 225 } 226 227 /* Encrypt pad bytes in a separate operation */ 228 if (mechanism == CKM_AES_CBC_PAD) { 229 out_len -= AES_BLOCK_LEN; 230 } 231 232 in_buf = pData; 233 out_buf = pEncrypted; 234 } else { 235 /* 236 * Called by C_EncryptUpdate 237 * 238 * Add the lengths of last remaining data and current 239 * plaintext together to get the total input length. 240 */ 241 total_len = soft_aes_ctx->remain_len + ulDataLen; 242 243 /* 244 * If the total input length is less than one blocksize, 245 * or if the total input length is just one blocksize and 246 * the mechanism is CKM_AES_CBC_PAD, we will need to delay 247 * encryption until when more data comes in next 248 * C_EncryptUpdate or when C_EncryptFinal is called. 249 */ 250 if ((total_len < AES_BLOCK_LEN) || 251 ((mechanism == CKM_AES_CBC_PAD) && 252 (total_len == AES_BLOCK_LEN))) { 253 if (pEncrypted != NULL) { 254 /* 255 * Save input data and its length in 256 * the remaining buffer of AES context. 257 */ 258 (void) memcpy(soft_aes_ctx->data + 259 soft_aes_ctx->remain_len, pData, ulDataLen); 260 soft_aes_ctx->remain_len += ulDataLen; 261 } 262 263 /* Set encrypted data length to 0. */ 264 *pulEncryptedLen = 0; 265 return (CKR_OK); 266 } 267 268 /* Compute the length of remaing data. */ 269 remain = total_len % AES_BLOCK_LEN; 270 271 /* 272 * Make sure that the output length is a multiple of 273 * blocksize. 274 */ 275 out_len = total_len - remain; 276 277 /* 278 * If application asks for the length of the output buffer 279 * to hold the ciphertext? 280 */ 281 if (pEncrypted == NULL) { 282 *pulEncryptedLen = out_len; 283 return (CKR_OK); 284 } 285 286 /* Is the application-supplied buffer large enough? */ 287 if (*pulEncryptedLen < out_len) { 288 *pulEncryptedLen = out_len; 289 return (CKR_BUFFER_TOO_SMALL); 290 } 291 292 if (soft_aes_ctx->remain_len != 0) { 293 /* 294 * Copy last remaining data and current input data 295 * to the output buffer. 296 */ 297 (void) memmove(pEncrypted + soft_aes_ctx->remain_len, 298 pData, out_len - soft_aes_ctx->remain_len); 299 (void) memcpy(pEncrypted, soft_aes_ctx->data, 300 soft_aes_ctx->remain_len); 301 bzero(soft_aes_ctx->data, soft_aes_ctx->remain_len); 302 303 in_buf = pEncrypted; 304 } else { 305 in_buf = pData; 306 } 307 out_buf = pEncrypted; 308 } 309 310 /* 311 * Begin Encryption now. 312 */ 313 switch (mechanism) { 314 315 case CKM_AES_ECB: 316 { 317 318 ulong_t i; 319 uint8_t *tmp_inbuf; 320 uint8_t *tmp_outbuf; 321 322 for (i = 0; i < out_len; i += AES_BLOCK_LEN) { 323 tmp_inbuf = &in_buf[i]; 324 tmp_outbuf = &out_buf[i]; 325 /* Crunch one block of data for AES. */ 326 aes_encrypt_block(soft_aes_ctx->key_sched, 327 tmp_inbuf, tmp_outbuf); 328 } 329 330 if (update) { 331 /* 332 * For encrypt update, if there is a remaining 333 * data, save it and its length in the context. 334 */ 335 if (remain != 0) 336 (void) memcpy(soft_aes_ctx->data, pData + 337 (ulDataLen - remain), remain); 338 soft_aes_ctx->remain_len = remain; 339 } 340 341 *pulEncryptedLen = out_len; 342 343 break; 344 } 345 346 case CKM_AES_CBC: 347 case CKM_AES_CBC_PAD: 348 { 349 crypto_data_t out; 350 351 out.cd_format = CRYPTO_DATA_RAW; 352 out.cd_offset = 0; 353 out.cd_length = out_len; 354 out.cd_raw.iov_base = (char *)out_buf; 355 out.cd_raw.iov_len = out_len; 356 357 /* Encrypt multiple blocks of data. */ 358 rc = aes_encrypt_contiguous_blocks( 359 (aes_ctx_t *)soft_aes_ctx->aes_cbc, 360 (char *)in_buf, out_len, &out); 361 362 if (rc != 0) 363 goto encrypt_failed; 364 365 if (update) { 366 /* 367 * For encrypt update, if there is remaining data, 368 * save it and its length in the context. 369 */ 370 if (remain != 0) 371 (void) memcpy(soft_aes_ctx->data, pData + 372 (ulDataLen - remain), remain); 373 soft_aes_ctx->remain_len = remain; 374 } else if (mechanism == CKM_AES_CBC_PAD) { 375 /* 376 * Save the remainder of the input 377 * block in a temporary block because 378 * we dont want to overrun the buffer 379 * by tacking on pad bytes. 380 */ 381 CK_BYTE tmpblock[AES_BLOCK_LEN]; 382 (void) memcpy(tmpblock, in_buf + out_len, 383 ulDataLen - out_len); 384 soft_add_pkcs7_padding(tmpblock + 385 (ulDataLen - out_len), 386 AES_BLOCK_LEN, ulDataLen - out_len); 387 388 out.cd_offset = out_len; 389 out.cd_length = AES_BLOCK_LEN; 390 out.cd_raw.iov_base = (char *)out_buf; 391 out.cd_raw.iov_len = out_len + AES_BLOCK_LEN; 392 393 /* Encrypt last block containing pad bytes. */ 394 rc = aes_encrypt_contiguous_blocks( 395 (aes_ctx_t *)soft_aes_ctx->aes_cbc, 396 (char *)tmpblock, AES_BLOCK_LEN, &out); 397 398 out_len += AES_BLOCK_LEN; 399 } 400 401 if (rc == 0) { 402 *pulEncryptedLen = out_len; 403 break; 404 } 405 encrypt_failed: 406 *pulEncryptedLen = 0; 407 rv = CKR_FUNCTION_FAILED; 408 goto cleanup; 409 } 410 } /* end switch */ 411 412 if (update) 413 return (CKR_OK); 414 415 /* 416 * The following code will be executed if the caller is 417 * soft_encrypt() or an error occurred. The encryption 418 * operation will be terminated so we need to do some cleanup. 419 */ 420 cleanup: 421 (void) pthread_mutex_lock(&session_p->session_mutex); 422 aes_ctx = (aes_ctx_t *)soft_aes_ctx->aes_cbc; 423 if (aes_ctx != NULL) { 424 bzero(aes_ctx->ac_keysched, aes_ctx->ac_keysched_len); 425 free(soft_aes_ctx->aes_cbc); 426 } 427 428 bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len); 429 free(soft_aes_ctx->key_sched); 430 free(session_p->encrypt.context); 431 session_p->encrypt.context = NULL; 432 (void) pthread_mutex_unlock(&session_p->session_mutex); 433 434 return (rv); 435 } 436 437 438 /* 439 * soft_aes_decrypt_common() 440 * 441 * Arguments: 442 * session_p: pointer to soft_session_t struct 443 * pEncrypted: pointer to the input data to be decrypted 444 * ulEncryptedLen: length of the input data 445 * pData: pointer to the output data 446 * pulDataLen: pointer to the length of the output data 447 * Update: boolean flag indicates caller is soft_decrypt 448 * or soft_decrypt_update 449 * 450 * Description: 451 * This function calls the corresponding decrypt routine based 452 * on the mechanism. 453 * 454 * Returns: 455 * CKR_OK: success 456 * CKR_BUFFER_TOO_SMALL: the output buffer provided by application 457 * is too small 458 * CKR_ENCRYPTED_DATA_LEN_RANGE: the input data is not a multiple 459 * of blocksize 460 * CKR_FUNCTION_FAILED: decrypt function failed 461 */ 462 CK_RV 463 soft_aes_decrypt_common(soft_session_t *session_p, CK_BYTE_PTR pEncrypted, 464 CK_ULONG ulEncryptedLen, CK_BYTE_PTR pData, 465 CK_ULONG_PTR pulDataLen, boolean_t update) 466 { 467 468 int rc = 0; 469 CK_RV rv = CKR_OK; 470 soft_aes_ctx_t *soft_aes_ctx = 471 (soft_aes_ctx_t *)session_p->decrypt.context; 472 aes_ctx_t *aes_ctx; 473 CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism; 474 CK_BYTE *in_buf = NULL; 475 CK_BYTE *out_buf = NULL; 476 CK_ULONG out_len; 477 CK_ULONG total_len; 478 CK_ULONG remain; 479 480 /* 481 * AES only takes input length that is a multiple of 16 bytes 482 * for C_Decrypt function with the mechanism CKM_AES_ECB, 483 * CKM_AES_CBC or CKM_AES_CBC_PAD. 484 * 485 * AES allows any input length for C_DecryptUpdate function. 486 */ 487 if (!update) { 488 /* 489 * Called by C_Decrypt 490 */ 491 if ((ulEncryptedLen % AES_BLOCK_LEN) != 0) { 492 rv = CKR_ENCRYPTED_DATA_LEN_RANGE; 493 goto cleanup; 494 } 495 496 /* 497 * If application asks for the length of the output buffer 498 * to hold the plaintext? 499 */ 500 if (pData == NULL) { 501 *pulDataLen = ulEncryptedLen; 502 return (CKR_OK); 503 } 504 505 /* Is the application-supplied buffer large enough? */ 506 if (mechanism != CKM_AES_CBC_PAD) { 507 if (*pulDataLen < ulEncryptedLen) { 508 *pulDataLen = ulEncryptedLen; 509 return (CKR_BUFFER_TOO_SMALL); 510 } 511 out_len = ulEncryptedLen; 512 } else { 513 /* 514 * For CKM_AES_CBC_PAD, we don't know how 515 * many bytes for padding at this time, so 516 * we'd assume one block was padded. 517 */ 518 if (*pulDataLen < (ulEncryptedLen - AES_BLOCK_LEN)) { 519 *pulDataLen = ulEncryptedLen - AES_BLOCK_LEN; 520 return (CKR_BUFFER_TOO_SMALL); 521 } 522 out_len = ulEncryptedLen - AES_BLOCK_LEN; 523 } 524 in_buf = pEncrypted; 525 out_buf = pData; 526 } else { 527 /* 528 * Called by C_DecryptUpdate 529 * 530 * Add the lengths of last remaining data and current 531 * input data together to get the total input length. 532 */ 533 total_len = soft_aes_ctx->remain_len + ulEncryptedLen; 534 535 /* 536 * If the total input length is less than one blocksize, 537 * or if the total input length is just one blocksize and 538 * the mechanism is CKM_AES_CBC_PAD, we will need to delay 539 * decryption until when more data comes in next 540 * C_DecryptUpdate or when C_DecryptFinal is called. 541 */ 542 if ((total_len < AES_BLOCK_LEN) || 543 ((mechanism == CKM_AES_CBC_PAD) && 544 (total_len == AES_BLOCK_LEN))) { 545 if (pData != NULL) { 546 /* 547 * Save input data and its length in 548 * the remaining buffer of AES context. 549 */ 550 (void) memcpy(soft_aes_ctx->data + 551 soft_aes_ctx->remain_len, 552 pEncrypted, ulEncryptedLen); 553 soft_aes_ctx->remain_len += ulEncryptedLen; 554 } 555 556 /* Set output data length to 0. */ 557 *pulDataLen = 0; 558 return (CKR_OK); 559 } 560 561 /* Compute the length of remaing data. */ 562 remain = total_len % AES_BLOCK_LEN; 563 564 /* 565 * Make sure that the output length is a multiple of 566 * blocksize. 567 */ 568 out_len = total_len - remain; 569 570 if (mechanism == CKM_AES_CBC_PAD) { 571 /* 572 * If the input data length is a multiple of 573 * blocksize, then save the last block of input 574 * data in the remaining buffer. C_DecryptFinal 575 * will handle this last block of data. 576 */ 577 if (remain == 0) { 578 remain = AES_BLOCK_LEN; 579 out_len -= AES_BLOCK_LEN; 580 } 581 } 582 583 /* 584 * If application asks for the length of the output buffer 585 * to hold the plaintext? 586 */ 587 if (pData == NULL) { 588 *pulDataLen = out_len; 589 return (CKR_OK); 590 } 591 592 /* 593 * Is the application-supplied buffer large enough? 594 */ 595 if (*pulDataLen < out_len) { 596 *pulDataLen = out_len; 597 return (CKR_BUFFER_TOO_SMALL); 598 } 599 600 if (soft_aes_ctx->remain_len != 0) { 601 /* 602 * Copy last remaining data and current input data 603 * to the output buffer. 604 */ 605 (void) memmove(pData + soft_aes_ctx->remain_len, 606 pEncrypted, out_len - soft_aes_ctx->remain_len); 607 (void) memcpy(pData, soft_aes_ctx->data, 608 soft_aes_ctx->remain_len); 609 bzero(soft_aes_ctx->data, soft_aes_ctx->remain_len); 610 611 in_buf = pData; 612 } else { 613 in_buf = pEncrypted; 614 } 615 out_buf = pData; 616 } 617 618 /* 619 * Begin Decryption. 620 */ 621 switch (mechanism) { 622 623 case CKM_AES_ECB: 624 { 625 626 ulong_t i; 627 uint8_t *tmp_inbuf; 628 uint8_t *tmp_outbuf; 629 630 for (i = 0; i < out_len; i += AES_BLOCK_LEN) { 631 tmp_inbuf = &in_buf[i]; 632 tmp_outbuf = &out_buf[i]; 633 /* Crunch one block of data for AES. */ 634 aes_decrypt_block(soft_aes_ctx->key_sched, 635 tmp_inbuf, tmp_outbuf); 636 } 637 638 if (update) { 639 /* 640 * For decrypt update, if there is a remaining 641 * data, save it and its length in the context. 642 */ 643 if (remain != 0) 644 (void) memcpy(soft_aes_ctx->data, pEncrypted + 645 (ulEncryptedLen - remain), remain); 646 soft_aes_ctx->remain_len = remain; 647 } 648 649 *pulDataLen = out_len; 650 651 break; 652 } 653 654 case CKM_AES_CBC: 655 case CKM_AES_CBC_PAD: 656 { 657 crypto_data_t out; 658 CK_ULONG rem_len; 659 uint8_t last_block[AES_BLOCK_LEN]; 660 661 out.cd_format = CRYPTO_DATA_RAW; 662 out.cd_offset = 0; 663 out.cd_length = out_len; 664 out.cd_raw.iov_base = (char *)out_buf; 665 out.cd_raw.iov_len = out_len; 666 667 /* Decrypt multiple blocks of data. */ 668 rc = aes_decrypt_contiguous_blocks( 669 (aes_ctx_t *)soft_aes_ctx->aes_cbc, 670 (char *)in_buf, out_len, &out); 671 672 if (rc != 0) 673 goto decrypt_failed; 674 675 if ((mechanism == CKM_AES_CBC_PAD) && (!update)) { 676 /* Decrypt last block containing pad bytes. */ 677 out.cd_offset = 0; 678 out.cd_length = AES_BLOCK_LEN; 679 out.cd_raw.iov_base = (char *)last_block; 680 out.cd_raw.iov_len = AES_BLOCK_LEN; 681 682 /* Decrypt last block containing pad bytes. */ 683 rc = aes_decrypt_contiguous_blocks( 684 (aes_ctx_t *)soft_aes_ctx->aes_cbc, 685 (char *)in_buf + out_len, AES_BLOCK_LEN, &out); 686 687 if (rc != 0) 688 goto decrypt_failed; 689 690 /* 691 * Remove padding bytes after decryption of 692 * ciphertext block to produce the original 693 * plaintext. 694 */ 695 rv = soft_remove_pkcs7_padding(last_block, 696 AES_BLOCK_LEN, &rem_len, AES_BLOCK_LEN); 697 if (rv == CKR_OK) { 698 if (rem_len != 0) 699 (void) memcpy(out_buf + out_len, 700 last_block, rem_len); 701 *pulDataLen = out_len + rem_len; 702 } else { 703 *pulDataLen = 0; 704 goto cleanup; 705 } 706 } else { 707 *pulDataLen = out_len; 708 } 709 710 if (update) { 711 /* 712 * For decrypt update, if there is remaining data, 713 * save it and its length in the context. 714 */ 715 if (remain != 0) 716 (void) memcpy(soft_aes_ctx->data, pEncrypted + 717 (ulEncryptedLen - remain), remain); 718 soft_aes_ctx->remain_len = remain; 719 } 720 721 if (rc == 0) 722 break; 723 decrypt_failed: 724 *pulDataLen = 0; 725 rv = CKR_FUNCTION_FAILED; 726 goto cleanup; 727 } 728 } /* end switch */ 729 730 if (update) 731 return (CKR_OK); 732 733 /* 734 * The following code will be executed if the caller is 735 * soft_decrypt() or an error occurred. The decryption 736 * operation will be terminated so we need to do some cleanup. 737 */ 738 cleanup: 739 (void) pthread_mutex_lock(&session_p->session_mutex); 740 aes_ctx = (aes_ctx_t *)soft_aes_ctx->aes_cbc; 741 if (aes_ctx != NULL) { 742 bzero(aes_ctx->ac_keysched, aes_ctx->ac_keysched_len); 743 free(soft_aes_ctx->aes_cbc); 744 } 745 746 bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len); 747 free(soft_aes_ctx->key_sched); 748 free(session_p->decrypt.context); 749 session_p->decrypt.context = NULL; 750 (void) pthread_mutex_unlock(&session_p->session_mutex); 751 752 return (rv); 753 } 754 755 756 /* 757 * Allocate and initialize a context for AES CBC mode of operation. 758 */ 759 void * 760 aes_cbc_ctx_init(void *key_sched, size_t size, uint8_t *ivec) 761 { 762 763 aes_ctx_t *aes_ctx; 764 765 if ((aes_ctx = calloc(1, sizeof (aes_ctx_t))) == NULL) 766 return (NULL); 767 768 aes_ctx->ac_keysched = key_sched; 769 770 (void) memcpy(&aes_ctx->ac_iv[0], ivec, AES_BLOCK_LEN); 771 772 aes_ctx->ac_lastp = (uint8_t *)aes_ctx->ac_iv; 773 aes_ctx->ac_keysched_len = size; 774 aes_ctx->ac_flags |= AES_CBC_MODE; 775 776 return ((void *)aes_ctx); 777 778 } 779