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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <pthread.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <strings.h> 33 #include <sys/types.h> 34 #include <security/cryptoki.h> 35 #include <aes_cbc_crypt.h> 36 #include <aes_impl.h> 37 #include "softSession.h" 38 #include "softObject.h" 39 #include "softCrypt.h" 40 41 /* 42 * Allocate context for the active encryption or decryption operation, and 43 * generate AES key schedule to speed up the operation. 44 */ 45 CK_RV 46 soft_aes_crypt_init_common(soft_session_t *session_p, 47 CK_MECHANISM_PTR pMechanism, soft_object_t *key_p, 48 boolean_t encrypt) 49 { 50 size_t size; 51 soft_aes_ctx_t *soft_aes_ctx; 52 53 soft_aes_ctx = calloc(1, sizeof (soft_aes_ctx_t)); 54 if (soft_aes_ctx == NULL) { 55 return (CKR_HOST_MEMORY); 56 } 57 58 soft_aes_ctx->key_sched = aes_alloc_keysched(&size, 0); 59 60 if (soft_aes_ctx->key_sched == NULL) { 61 free(soft_aes_ctx); 62 return (CKR_HOST_MEMORY); 63 } 64 65 soft_aes_ctx->keysched_len = size; 66 67 (void) pthread_mutex_lock(&session_p->session_mutex); 68 if (encrypt) { 69 /* Called by C_EncryptInit. */ 70 session_p->encrypt.context = soft_aes_ctx; 71 session_p->encrypt.mech.mechanism = pMechanism->mechanism; 72 } else { 73 /* Called by C_DecryptInit. */ 74 session_p->decrypt.context = soft_aes_ctx; 75 session_p->decrypt.mech.mechanism = pMechanism->mechanism; 76 } 77 (void) pthread_mutex_unlock(&session_p->session_mutex); 78 79 /* 80 * If this is a non-sensitive key and it does NOT have 81 * a key schedule yet, then allocate one and expand it. 82 * Otherwise, if it's a non-sensitive key, and it DOES have 83 * a key schedule already attached to it, just copy the 84 * pre-expanded schedule to the context and avoid the 85 * extra key schedule expansion operation. 86 */ 87 if (!(key_p->bool_attr_mask & SENSITIVE_BOOL_ON)) { 88 if (OBJ_SEC(key_p)->key_sched == NULL) { 89 void *ks; 90 ks = aes_alloc_keysched(&size, 0); 91 if (ks != NULL) { 92 OBJ_SEC(key_p)->key_sched = ks; 93 OBJ_SEC(key_p)->keysched_len = size; 94 } else { 95 free(soft_aes_ctx); 96 return (CKR_HOST_MEMORY); 97 } 98 #ifdef __sparcv9 99 /* LINTED */ 100 aes_init_keysched(OBJ_SEC_VALUE(key_p), (uint_t) 101 (OBJ_SEC_VALUE_LEN(key_p) * 8), 102 OBJ_KEY_SCHED(key_p)); 103 #else /* !__sparcv9 */ 104 aes_init_keysched(OBJ_SEC_VALUE(key_p), 105 (OBJ_SEC_VALUE_LEN(key_p) * 8), 106 OBJ_KEY_SCHED(key_p)); 107 #endif /* __sparcv9 */ 108 } 109 (void) memcpy(soft_aes_ctx->key_sched, OBJ_KEY_SCHED(key_p), 110 OBJ_KEY_SCHED_LEN(key_p)); 111 soft_aes_ctx->keysched_len = OBJ_KEY_SCHED_LEN(key_p); 112 } else { 113 /* 114 * Initialize key schedule for AES. aes_init_keysched() 115 * requires key length in bits. 116 */ 117 #ifdef __sparcv9 118 /* LINTED */ 119 aes_init_keysched(OBJ_SEC_VALUE(key_p), (uint_t) 120 (OBJ_SEC_VALUE_LEN(key_p) * 8), 121 soft_aes_ctx->key_sched); 122 #else /* !__sparcv9 */ 123 aes_init_keysched(OBJ_SEC_VALUE(key_p), 124 (OBJ_SEC_VALUE_LEN(key_p) * 8), 125 soft_aes_ctx->key_sched); 126 #endif /* __sparcv9 */ 127 } 128 return (CKR_OK); 129 } 130 131 132 /* 133 * soft_aes_encrypt_common() 134 * 135 * Arguments: 136 * session_p: pointer to soft_session_t struct 137 * pData: pointer to the input data to be encrypted 138 * ulDataLen: length of the input data 139 * pEncrypted: pointer to the output data after encryption 140 * pulEncryptedLen: pointer to the length of the output data 141 * update: boolean flag indicates caller is soft_encrypt 142 * or soft_encrypt_update 143 * 144 * Description: 145 * This function calls the corresponding encrypt routine based 146 * on the mechanism. 147 * 148 * Returns: 149 * CKR_OK: success 150 * CKR_BUFFER_TOO_SMALL: the output buffer provided by application 151 * is too small 152 * CKR_FUNCTION_FAILED: encrypt function failed 153 * CKR_DATA_LEN_RANGE: the input data is not a multiple of blocksize 154 */ 155 CK_RV 156 soft_aes_encrypt_common(soft_session_t *session_p, CK_BYTE_PTR pData, 157 CK_ULONG ulDataLen, CK_BYTE_PTR pEncrypted, 158 CK_ULONG_PTR pulEncryptedLen, boolean_t update) 159 { 160 161 int rc = 0; 162 CK_RV rv = CKR_OK; 163 soft_aes_ctx_t *soft_aes_ctx = 164 (soft_aes_ctx_t *)session_p->encrypt.context; 165 aes_ctx_t *aes_ctx; 166 CK_MECHANISM_TYPE mechanism = session_p->encrypt.mech.mechanism; 167 CK_BYTE *in_buf = NULL; 168 CK_BYTE *out_buf = NULL; 169 CK_ULONG out_len; 170 CK_ULONG total_len; 171 CK_ULONG remain; 172 173 /* 174 * AES only takes input length that is a multiple of blocksize 175 * for C_Encrypt function with the mechanism CKM_AES_ECB or 176 * CKM_AES_CBC. 177 * 178 * AES allows any input length for C_Encrypt function with the 179 * mechanism CKM_AES_CBC_PAD and for C_EncryptUpdate function. 180 */ 181 if ((!update) && (mechanism != CKM_AES_CBC_PAD)) { 182 if ((ulDataLen % AES_BLOCK_LEN) != 0) { 183 rv = CKR_DATA_LEN_RANGE; 184 goto cleanup; 185 } 186 } 187 188 if (!update) { 189 /* 190 * Called by C_Encrypt 191 */ 192 if (mechanism == CKM_AES_CBC_PAD) { 193 /* 194 * For CKM_AES_CBC_PAD, compute output length to 195 * count for the padding. If the length of input 196 * data is a multiple of blocksize, then make output 197 * length to be the sum of the input length and 198 * one blocksize. Otherwise, output length will 199 * be rounded up to the next multiple of blocksize. 200 */ 201 out_len = AES_BLOCK_LEN * 202 (ulDataLen / AES_BLOCK_LEN + 1); 203 } else { 204 /* 205 * For non-padding mode, the output length will 206 * be same as the input length. 207 */ 208 out_len = ulDataLen; 209 } 210 211 /* 212 * If application asks for the length of the output buffer 213 * to hold the ciphertext? 214 */ 215 if (pEncrypted == NULL) { 216 *pulEncryptedLen = out_len; 217 return (CKR_OK); 218 } 219 220 /* Is the application-supplied buffer large enough? */ 221 if (*pulEncryptedLen < out_len) { 222 *pulEncryptedLen = out_len; 223 return (CKR_BUFFER_TOO_SMALL); 224 } 225 226 /* Encrypt pad bytes in a separate operation */ 227 if (mechanism == CKM_AES_CBC_PAD) { 228 out_len -= AES_BLOCK_LEN; 229 } 230 231 in_buf = pData; 232 out_buf = pEncrypted; 233 } else { 234 /* 235 * Called by C_EncryptUpdate 236 * 237 * Add the lengths of last remaining data and current 238 * plaintext together to get the total input length. 239 */ 240 total_len = soft_aes_ctx->remain_len + ulDataLen; 241 242 /* 243 * If the total input length is less than one blocksize, 244 * or if the total input length is just one blocksize and 245 * the mechanism is CKM_AES_CBC_PAD, we will need to delay 246 * encryption until when more data comes in next 247 * C_EncryptUpdate or when C_EncryptFinal is called. 248 */ 249 if ((total_len < AES_BLOCK_LEN) || 250 ((mechanism == CKM_AES_CBC_PAD) && 251 (total_len == AES_BLOCK_LEN))) { 252 if (pEncrypted != NULL) { 253 /* 254 * Save input data and its length in 255 * the remaining buffer of AES context. 256 */ 257 (void) memcpy(soft_aes_ctx->data + 258 soft_aes_ctx->remain_len, pData, ulDataLen); 259 soft_aes_ctx->remain_len += ulDataLen; 260 } 261 262 /* Set encrypted data length to 0. */ 263 *pulEncryptedLen = 0; 264 return (CKR_OK); 265 } 266 267 /* Compute the length of remaing data. */ 268 remain = total_len % AES_BLOCK_LEN; 269 270 /* 271 * Make sure that the output length is a multiple of 272 * blocksize. 273 */ 274 out_len = total_len - remain; 275 276 /* 277 * If application asks for the length of the output buffer 278 * to hold the ciphertext? 279 */ 280 if (pEncrypted == NULL) { 281 *pulEncryptedLen = out_len; 282 return (CKR_OK); 283 } 284 285 /* Is the application-supplied buffer large enough? */ 286 if (*pulEncryptedLen < out_len) { 287 *pulEncryptedLen = out_len; 288 return (CKR_BUFFER_TOO_SMALL); 289 } 290 291 if (soft_aes_ctx->remain_len != 0) { 292 /* 293 * Copy last remaining data and current input data 294 * to the output buffer. 295 */ 296 (void) memmove(pEncrypted + soft_aes_ctx->remain_len, 297 pData, out_len - soft_aes_ctx->remain_len); 298 (void) memcpy(pEncrypted, soft_aes_ctx->data, 299 soft_aes_ctx->remain_len); 300 bzero(soft_aes_ctx->data, soft_aes_ctx->remain_len); 301 302 in_buf = pEncrypted; 303 } else { 304 in_buf = pData; 305 } 306 out_buf = pEncrypted; 307 } 308 309 /* 310 * Begin Encryption now. 311 */ 312 switch (mechanism) { 313 314 case CKM_AES_ECB: 315 { 316 317 ulong_t i; 318 uint8_t *tmp_inbuf; 319 uint8_t *tmp_outbuf; 320 321 for (i = 0; i < out_len; i += AES_BLOCK_LEN) { 322 tmp_inbuf = &in_buf[i]; 323 tmp_outbuf = &out_buf[i]; 324 /* Crunch one block of data for AES. */ 325 aes_encrypt_block(soft_aes_ctx->key_sched, 326 tmp_inbuf, tmp_outbuf); 327 } 328 329 if (update) { 330 /* 331 * For encrypt update, if there is a remaining 332 * data, save it and its length in the context. 333 */ 334 if (remain != 0) 335 (void) memcpy(soft_aes_ctx->data, pData + 336 (ulDataLen - remain), remain); 337 soft_aes_ctx->remain_len = remain; 338 } 339 340 *pulEncryptedLen = out_len; 341 342 break; 343 } 344 345 case CKM_AES_CBC: 346 case CKM_AES_CBC_PAD: 347 { 348 crypto_data_t out; 349 350 out.cd_format = CRYPTO_DATA_RAW; 351 out.cd_offset = 0; 352 out.cd_length = out_len; 353 out.cd_raw.iov_base = (char *)out_buf; 354 out.cd_raw.iov_len = out_len; 355 356 /* Encrypt multiple blocks of data. */ 357 rc = aes_encrypt_contiguous_blocks( 358 (aes_ctx_t *)soft_aes_ctx->aes_cbc, 359 (char *)in_buf, out_len, &out); 360 361 if (rc != 0) 362 goto encrypt_failed; 363 364 if (update) { 365 /* 366 * For encrypt update, if there is remaining data, 367 * save it and its length in the context. 368 */ 369 if (remain != 0) 370 (void) memcpy(soft_aes_ctx->data, pData + 371 (ulDataLen - remain), remain); 372 soft_aes_ctx->remain_len = remain; 373 } else if (mechanism == CKM_AES_CBC_PAD) { 374 /* 375 * Save the remainder of the input 376 * block in a temporary block because 377 * we dont want to overrun the buffer 378 * by tacking on pad bytes. 379 */ 380 CK_BYTE tmpblock[AES_BLOCK_LEN]; 381 (void) memcpy(tmpblock, in_buf + out_len, 382 ulDataLen - out_len); 383 soft_add_pkcs7_padding(tmpblock + 384 (ulDataLen - out_len), 385 AES_BLOCK_LEN, ulDataLen - out_len); 386 387 out.cd_offset = out_len; 388 out.cd_length = AES_BLOCK_LEN; 389 out.cd_raw.iov_base = (char *)out_buf; 390 out.cd_raw.iov_len = out_len + AES_BLOCK_LEN; 391 392 /* Encrypt last block containing pad bytes. */ 393 rc = aes_encrypt_contiguous_blocks( 394 (aes_ctx_t *)soft_aes_ctx->aes_cbc, 395 (char *)tmpblock, AES_BLOCK_LEN, &out); 396 397 out_len += AES_BLOCK_LEN; 398 } 399 400 if (rc == 0) { 401 *pulEncryptedLen = out_len; 402 break; 403 } 404 encrypt_failed: 405 *pulEncryptedLen = 0; 406 rv = CKR_FUNCTION_FAILED; 407 goto cleanup; 408 } 409 } /* end switch */ 410 411 if (update) 412 return (CKR_OK); 413 414 /* 415 * The following code will be executed if the caller is 416 * soft_encrypt() or an error occurred. The encryption 417 * operation will be terminated so we need to do some cleanup. 418 */ 419 cleanup: 420 (void) pthread_mutex_lock(&session_p->session_mutex); 421 aes_ctx = (aes_ctx_t *)soft_aes_ctx->aes_cbc; 422 if (aes_ctx != NULL) { 423 bzero(aes_ctx->ac_keysched, aes_ctx->ac_keysched_len); 424 free(soft_aes_ctx->aes_cbc); 425 } 426 427 bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len); 428 free(soft_aes_ctx->key_sched); 429 free(session_p->encrypt.context); 430 session_p->encrypt.context = NULL; 431 (void) pthread_mutex_unlock(&session_p->session_mutex); 432 433 return (rv); 434 } 435 436 437 /* 438 * soft_aes_decrypt_common() 439 * 440 * Arguments: 441 * session_p: pointer to soft_session_t struct 442 * pEncrypted: pointer to the input data to be decrypted 443 * ulEncryptedLen: length of the input data 444 * pData: pointer to the output data 445 * pulDataLen: pointer to the length of the output data 446 * Update: boolean flag indicates caller is soft_decrypt 447 * or soft_decrypt_update 448 * 449 * Description: 450 * This function calls the corresponding decrypt routine based 451 * on the mechanism. 452 * 453 * Returns: 454 * CKR_OK: success 455 * CKR_BUFFER_TOO_SMALL: the output buffer provided by application 456 * is too small 457 * CKR_ENCRYPTED_DATA_LEN_RANGE: the input data is not a multiple 458 * of blocksize 459 * CKR_FUNCTION_FAILED: decrypt function failed 460 */ 461 CK_RV 462 soft_aes_decrypt_common(soft_session_t *session_p, CK_BYTE_PTR pEncrypted, 463 CK_ULONG ulEncryptedLen, CK_BYTE_PTR pData, 464 CK_ULONG_PTR pulDataLen, boolean_t update) 465 { 466 467 int rc = 0; 468 CK_RV rv = CKR_OK; 469 soft_aes_ctx_t *soft_aes_ctx = 470 (soft_aes_ctx_t *)session_p->decrypt.context; 471 aes_ctx_t *aes_ctx; 472 CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism; 473 CK_BYTE *in_buf = NULL; 474 CK_BYTE *out_buf = NULL; 475 CK_ULONG out_len; 476 CK_ULONG total_len; 477 CK_ULONG remain; 478 479 /* 480 * AES only takes input length that is a multiple of 16 bytes 481 * for C_Decrypt function with the mechanism CKM_AES_ECB, 482 * CKM_AES_CBC or CKM_AES_CBC_PAD. 483 * 484 * AES allows any input length for C_DecryptUpdate function. 485 */ 486 if (!update) { 487 /* 488 * Called by C_Decrypt 489 */ 490 if ((ulEncryptedLen % AES_BLOCK_LEN) != 0) { 491 rv = CKR_ENCRYPTED_DATA_LEN_RANGE; 492 goto cleanup; 493 } 494 495 /* 496 * If application asks for the length of the output buffer 497 * to hold the plaintext? 498 */ 499 if (pData == NULL) { 500 *pulDataLen = ulEncryptedLen; 501 return (CKR_OK); 502 } 503 504 /* Is the application-supplied buffer large enough? */ 505 if (mechanism != CKM_AES_CBC_PAD) { 506 if (*pulDataLen < ulEncryptedLen) { 507 *pulDataLen = ulEncryptedLen; 508 return (CKR_BUFFER_TOO_SMALL); 509 } 510 out_len = ulEncryptedLen; 511 } else { 512 /* 513 * For CKM_AES_CBC_PAD, we don't know how 514 * many bytes for padding at this time, so 515 * we'd assume one block was padded. 516 */ 517 if (*pulDataLen < (ulEncryptedLen - AES_BLOCK_LEN)) { 518 *pulDataLen = ulEncryptedLen - AES_BLOCK_LEN; 519 return (CKR_BUFFER_TOO_SMALL); 520 } 521 out_len = ulEncryptedLen - AES_BLOCK_LEN; 522 } 523 in_buf = pEncrypted; 524 out_buf = pData; 525 } else { 526 /* 527 * Called by C_DecryptUpdate 528 * 529 * Add the lengths of last remaining data and current 530 * input data together to get the total input length. 531 */ 532 total_len = soft_aes_ctx->remain_len + ulEncryptedLen; 533 534 /* 535 * If the total input length is less than one blocksize, 536 * or if the total input length is just one blocksize and 537 * the mechanism is CKM_AES_CBC_PAD, we will need to delay 538 * decryption until when more data comes in next 539 * C_DecryptUpdate or when C_DecryptFinal is called. 540 */ 541 if ((total_len < AES_BLOCK_LEN) || 542 ((mechanism == CKM_AES_CBC_PAD) && 543 (total_len == AES_BLOCK_LEN))) { 544 if (pData != NULL) { 545 /* 546 * Save input data and its length in 547 * the remaining buffer of AES context. 548 */ 549 (void) memcpy(soft_aes_ctx->data + 550 soft_aes_ctx->remain_len, 551 pEncrypted, ulEncryptedLen); 552 soft_aes_ctx->remain_len += ulEncryptedLen; 553 } 554 555 /* Set output data length to 0. */ 556 *pulDataLen = 0; 557 return (CKR_OK); 558 } 559 560 /* Compute the length of remaing data. */ 561 remain = total_len % AES_BLOCK_LEN; 562 563 /* 564 * Make sure that the output length is a multiple of 565 * blocksize. 566 */ 567 out_len = total_len - remain; 568 569 if (mechanism == CKM_AES_CBC_PAD) { 570 /* 571 * If the input data length is a multiple of 572 * blocksize, then save the last block of input 573 * data in the remaining buffer. C_DecryptFinal 574 * will handle this last block of data. 575 */ 576 if (remain == 0) { 577 remain = AES_BLOCK_LEN; 578 out_len -= AES_BLOCK_LEN; 579 } 580 } 581 582 /* 583 * If application asks for the length of the output buffer 584 * to hold the plaintext? 585 */ 586 if (pData == NULL) { 587 *pulDataLen = out_len; 588 return (CKR_OK); 589 } 590 591 /* 592 * Is the application-supplied buffer large enough? 593 */ 594 if (*pulDataLen < out_len) { 595 *pulDataLen = out_len; 596 return (CKR_BUFFER_TOO_SMALL); 597 } 598 599 if (soft_aes_ctx->remain_len != 0) { 600 /* 601 * Copy last remaining data and current input data 602 * to the output buffer. 603 */ 604 (void) memmove(pData + soft_aes_ctx->remain_len, 605 pEncrypted, out_len - soft_aes_ctx->remain_len); 606 (void) memcpy(pData, soft_aes_ctx->data, 607 soft_aes_ctx->remain_len); 608 bzero(soft_aes_ctx->data, soft_aes_ctx->remain_len); 609 610 in_buf = pData; 611 } else { 612 in_buf = pEncrypted; 613 } 614 out_buf = pData; 615 } 616 617 /* 618 * Begin Decryption. 619 */ 620 switch (mechanism) { 621 622 case CKM_AES_ECB: 623 { 624 625 ulong_t i; 626 uint8_t *tmp_inbuf; 627 uint8_t *tmp_outbuf; 628 629 for (i = 0; i < out_len; i += AES_BLOCK_LEN) { 630 tmp_inbuf = &in_buf[i]; 631 tmp_outbuf = &out_buf[i]; 632 /* Crunch one block of data for AES. */ 633 aes_decrypt_block(soft_aes_ctx->key_sched, 634 tmp_inbuf, tmp_outbuf); 635 } 636 637 if (update) { 638 /* 639 * For decrypt update, if there is a remaining 640 * data, save it and its length in the context. 641 */ 642 if (remain != 0) 643 (void) memcpy(soft_aes_ctx->data, pEncrypted + 644 (ulEncryptedLen - remain), remain); 645 soft_aes_ctx->remain_len = remain; 646 } 647 648 *pulDataLen = out_len; 649 650 break; 651 } 652 653 case CKM_AES_CBC: 654 case CKM_AES_CBC_PAD: 655 { 656 crypto_data_t out; 657 CK_ULONG rem_len; 658 uint8_t last_block[AES_BLOCK_LEN]; 659 660 out.cd_format = CRYPTO_DATA_RAW; 661 out.cd_offset = 0; 662 out.cd_length = out_len; 663 out.cd_raw.iov_base = (char *)out_buf; 664 out.cd_raw.iov_len = out_len; 665 666 /* Decrypt multiple blocks of data. */ 667 rc = aes_decrypt_contiguous_blocks( 668 (aes_ctx_t *)soft_aes_ctx->aes_cbc, 669 (char *)in_buf, out_len, &out); 670 671 if (rc != 0) 672 goto decrypt_failed; 673 674 if ((mechanism == CKM_AES_CBC_PAD) && (!update)) { 675 /* Decrypt last block containing pad bytes. */ 676 out.cd_offset = 0; 677 out.cd_length = AES_BLOCK_LEN; 678 out.cd_raw.iov_base = (char *)last_block; 679 out.cd_raw.iov_len = AES_BLOCK_LEN; 680 681 /* Decrypt last block containing pad bytes. */ 682 rc = aes_decrypt_contiguous_blocks( 683 (aes_ctx_t *)soft_aes_ctx->aes_cbc, 684 (char *)in_buf + out_len, AES_BLOCK_LEN, &out); 685 686 if (rc != 0) 687 goto decrypt_failed; 688 689 /* 690 * Remove padding bytes after decryption of 691 * ciphertext block to produce the original 692 * plaintext. 693 */ 694 rv = soft_remove_pkcs7_padding(last_block, 695 AES_BLOCK_LEN, &rem_len, AES_BLOCK_LEN); 696 if (rv == CKR_OK) { 697 if (rem_len != 0) 698 (void) memcpy(out_buf + out_len, 699 last_block, rem_len); 700 *pulDataLen = out_len + rem_len; 701 } else { 702 *pulDataLen = 0; 703 goto cleanup; 704 } 705 } else { 706 *pulDataLen = out_len; 707 } 708 709 if (update) { 710 /* 711 * For decrypt update, if there is remaining data, 712 * save it and its length in the context. 713 */ 714 if (remain != 0) 715 (void) memcpy(soft_aes_ctx->data, pEncrypted + 716 (ulEncryptedLen - remain), remain); 717 soft_aes_ctx->remain_len = remain; 718 } 719 720 if (rc == 0) 721 break; 722 decrypt_failed: 723 *pulDataLen = 0; 724 rv = CKR_FUNCTION_FAILED; 725 goto cleanup; 726 } 727 } /* end switch */ 728 729 if (update) 730 return (CKR_OK); 731 732 /* 733 * The following code will be executed if the caller is 734 * soft_decrypt() or an error occurred. The decryption 735 * operation will be terminated so we need to do some cleanup. 736 */ 737 cleanup: 738 (void) pthread_mutex_lock(&session_p->session_mutex); 739 aes_ctx = (aes_ctx_t *)soft_aes_ctx->aes_cbc; 740 if (aes_ctx != NULL) { 741 bzero(aes_ctx->ac_keysched, aes_ctx->ac_keysched_len); 742 free(soft_aes_ctx->aes_cbc); 743 } 744 745 bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len); 746 free(soft_aes_ctx->key_sched); 747 free(session_p->decrypt.context); 748 session_p->decrypt.context = NULL; 749 (void) pthread_mutex_unlock(&session_p->session_mutex); 750 751 return (rv); 752 } 753 754 755 /* 756 * Allocate and initialize a context for AES CBC mode of operation. 757 */ 758 void * 759 aes_cbc_ctx_init(void *key_sched, size_t size, uint8_t *ivec) 760 { 761 762 aes_ctx_t *aes_ctx; 763 764 if ((aes_ctx = calloc(1, sizeof (aes_ctx_t))) == NULL) 765 return (NULL); 766 767 aes_ctx->ac_keysched = key_sched; 768 769 (void) memcpy(&aes_ctx->ac_iv[0], ivec, AES_BLOCK_LEN); 770 771 aes_ctx->ac_lastp = (uint8_t *)aes_ctx->ac_iv; 772 aes_ctx->ac_keysched_len = size; 773 aes_ctx->ac_flags |= AES_CBC_MODE; 774 775 return ((void *)aes_ctx); 776 777 } 778