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 "softSession.h" 35 #include "softObject.h" 36 #include "softCrypt.h" 37 #include <aes_impl.h> 38 39 /* 40 * Allocate context for the active encryption or decryption operation, and 41 * generate AES key schedule to speed up the operation. 42 */ 43 CK_RV 44 soft_aes_crypt_init_common(soft_session_t *session_p, 45 CK_MECHANISM_PTR pMechanism, soft_object_t *key_p, 46 boolean_t encrypt) 47 { 48 size_t size; 49 soft_aes_ctx_t *soft_aes_ctx; 50 51 soft_aes_ctx = calloc(1, sizeof (soft_aes_ctx_t)); 52 if (soft_aes_ctx == NULL) { 53 return (CKR_HOST_MEMORY); 54 } 55 56 soft_aes_ctx->key_sched = aes_alloc_keysched(&size, 0); 57 58 if (soft_aes_ctx->key_sched == NULL) { 59 free(soft_aes_ctx); 60 return (CKR_HOST_MEMORY); 61 } 62 63 soft_aes_ctx->keysched_len = size; 64 65 (void) pthread_mutex_lock(&session_p->session_mutex); 66 if (encrypt) { 67 /* Called by C_EncryptInit. */ 68 session_p->encrypt.context = soft_aes_ctx; 69 session_p->encrypt.mech.mechanism = pMechanism->mechanism; 70 } else { 71 /* Called by C_DecryptInit. */ 72 session_p->decrypt.context = soft_aes_ctx; 73 session_p->decrypt.mech.mechanism = pMechanism->mechanism; 74 } 75 (void) pthread_mutex_unlock(&session_p->session_mutex); 76 77 /* 78 * If this is a non-sensitive key and it does NOT have 79 * a key schedule yet, then allocate one and expand it. 80 * Otherwise, if it's a non-sensitive key, and it DOES have 81 * a key schedule already attached to it, just copy the 82 * pre-expanded schedule to the context and avoid the 83 * extra key schedule expansion operation. 84 */ 85 if (!(key_p->bool_attr_mask & SENSITIVE_BOOL_ON)) { 86 if (OBJ_KEY_SCHED(key_p) == NULL) { 87 void *ks; 88 89 (void) pthread_mutex_lock(&key_p->object_mutex); 90 if (OBJ_KEY_SCHED(key_p) == NULL) { 91 ks = aes_alloc_keysched(&size, 0); 92 if (ks == NULL) { 93 (void) pthread_mutex_unlock( 94 &key_p->object_mutex); 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), ks); 102 #else /* !__sparcv9 */ 103 aes_init_keysched(OBJ_SEC_VALUE(key_p), 104 (OBJ_SEC_VALUE_LEN(key_p) * 8), ks); 105 #endif /* __sparcv9 */ 106 OBJ_KEY_SCHED_LEN(key_p) = size; 107 OBJ_KEY_SCHED(key_p) = ks; 108 } 109 (void) pthread_mutex_unlock(&key_p->object_mutex); 110 } 111 (void) memcpy(soft_aes_ctx->key_sched, OBJ_KEY_SCHED(key_p), 112 OBJ_KEY_SCHED_LEN(key_p)); 113 soft_aes_ctx->keysched_len = OBJ_KEY_SCHED_LEN(key_p); 114 } else { 115 /* 116 * Initialize key schedule for AES. aes_init_keysched() 117 * requires key length in bits. 118 */ 119 #ifdef __sparcv9 120 /* LINTED */ 121 aes_init_keysched(OBJ_SEC_VALUE(key_p), (uint_t) 122 (OBJ_SEC_VALUE_LEN(key_p) * 8), soft_aes_ctx->key_sched); 123 #else /* !__sparcv9 */ 124 aes_init_keysched(OBJ_SEC_VALUE(key_p), 125 (OBJ_SEC_VALUE_LEN(key_p) * 8), 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 if (mechanism == CKM_AES_CTR) 174 goto do_encryption; 175 176 /* 177 * AES only takes input length that is a multiple of blocksize 178 * for C_Encrypt function with the mechanism CKM_AES_ECB or 179 * CKM_AES_CBC. 180 * 181 * AES allows any input length for C_Encrypt function with the 182 * mechanism CKM_AES_CBC_PAD and for C_EncryptUpdate function. 183 */ 184 if ((!update) && (mechanism != CKM_AES_CBC_PAD)) { 185 if ((ulDataLen % AES_BLOCK_LEN) != 0) { 186 rv = CKR_DATA_LEN_RANGE; 187 goto cleanup; 188 } 189 } 190 191 if (!update) { 192 /* 193 * Called by C_Encrypt 194 */ 195 if (mechanism == CKM_AES_CBC_PAD) { 196 /* 197 * For CKM_AES_CBC_PAD, compute output length to 198 * count for the padding. If the length of input 199 * data is a multiple of blocksize, then make output 200 * length to be the sum of the input length and 201 * one blocksize. Otherwise, output length will 202 * be rounded up to the next multiple of blocksize. 203 */ 204 out_len = AES_BLOCK_LEN * 205 (ulDataLen / AES_BLOCK_LEN + 1); 206 } else { 207 /* 208 * For non-padding mode, the output length will 209 * be same as the input length. 210 */ 211 out_len = ulDataLen; 212 } 213 214 /* 215 * If application asks for the length of the output buffer 216 * to hold the ciphertext? 217 */ 218 if (pEncrypted == NULL) { 219 *pulEncryptedLen = out_len; 220 return (CKR_OK); 221 } 222 223 /* Is the application-supplied buffer large enough? */ 224 if (*pulEncryptedLen < out_len) { 225 *pulEncryptedLen = out_len; 226 return (CKR_BUFFER_TOO_SMALL); 227 } 228 229 /* Encrypt pad bytes in a separate operation */ 230 if (mechanism == CKM_AES_CBC_PAD) { 231 out_len -= AES_BLOCK_LEN; 232 } 233 234 in_buf = pData; 235 out_buf = pEncrypted; 236 } else { 237 /* 238 * Called by C_EncryptUpdate 239 * 240 * Add the lengths of last remaining data and current 241 * plaintext together to get the total input length. 242 */ 243 total_len = soft_aes_ctx->remain_len + ulDataLen; 244 245 /* 246 * If the total input length is less than one blocksize, 247 * or if the total input length is just one blocksize and 248 * the mechanism is CKM_AES_CBC_PAD, we will need to delay 249 * encryption until when more data comes in next 250 * C_EncryptUpdate or when C_EncryptFinal is called. 251 */ 252 if ((total_len < AES_BLOCK_LEN) || 253 ((mechanism == CKM_AES_CBC_PAD) && 254 (total_len == AES_BLOCK_LEN))) { 255 if (pEncrypted != NULL) { 256 /* 257 * Save input data and its length in 258 * the remaining buffer of AES context. 259 */ 260 (void) memcpy(soft_aes_ctx->data + 261 soft_aes_ctx->remain_len, pData, ulDataLen); 262 soft_aes_ctx->remain_len += ulDataLen; 263 } 264 265 /* Set encrypted data length to 0. */ 266 *pulEncryptedLen = 0; 267 return (CKR_OK); 268 } 269 270 /* Compute the length of remaing data. */ 271 remain = total_len % AES_BLOCK_LEN; 272 273 /* 274 * Make sure that the output length is a multiple of 275 * blocksize. 276 */ 277 out_len = total_len - remain; 278 279 /* 280 * If application asks for the length of the output buffer 281 * to hold the ciphertext? 282 */ 283 if (pEncrypted == NULL) { 284 *pulEncryptedLen = out_len; 285 return (CKR_OK); 286 } 287 288 /* Is the application-supplied buffer large enough? */ 289 if (*pulEncryptedLen < out_len) { 290 *pulEncryptedLen = out_len; 291 return (CKR_BUFFER_TOO_SMALL); 292 } 293 294 if (soft_aes_ctx->remain_len != 0) { 295 /* 296 * Copy last remaining data and current input data 297 * to the output buffer. 298 */ 299 (void) memmove(pEncrypted + soft_aes_ctx->remain_len, 300 pData, out_len - soft_aes_ctx->remain_len); 301 (void) memcpy(pEncrypted, soft_aes_ctx->data, 302 soft_aes_ctx->remain_len); 303 bzero(soft_aes_ctx->data, soft_aes_ctx->remain_len); 304 305 in_buf = pEncrypted; 306 } else { 307 in_buf = pData; 308 } 309 out_buf = pEncrypted; 310 } 311 312 do_encryption: 313 /* 314 * Begin Encryption now. 315 */ 316 switch (mechanism) { 317 318 case CKM_AES_ECB: 319 { 320 321 ulong_t i; 322 uint8_t *tmp_inbuf; 323 uint8_t *tmp_outbuf; 324 325 for (i = 0; i < out_len; i += AES_BLOCK_LEN) { 326 tmp_inbuf = &in_buf[i]; 327 tmp_outbuf = &out_buf[i]; 328 /* Crunch one block of data for AES. */ 329 (void) aes_encrypt_block(soft_aes_ctx->key_sched, 330 tmp_inbuf, tmp_outbuf); 331 } 332 333 if (update) { 334 /* 335 * For encrypt update, if there is a remaining 336 * data, save it and its length in the context. 337 */ 338 if (remain != 0) 339 (void) memcpy(soft_aes_ctx->data, pData + 340 (ulDataLen - remain), remain); 341 soft_aes_ctx->remain_len = remain; 342 } 343 344 *pulEncryptedLen = out_len; 345 346 break; 347 } 348 349 case CKM_AES_CBC: 350 case CKM_AES_CBC_PAD: 351 { 352 crypto_data_t out; 353 354 out.cd_format = CRYPTO_DATA_RAW; 355 out.cd_offset = 0; 356 out.cd_length = out_len; 357 out.cd_raw.iov_base = (char *)out_buf; 358 out.cd_raw.iov_len = out_len; 359 360 /* Encrypt multiple blocks of data. */ 361 rc = aes_encrypt_contiguous_blocks( 362 (aes_ctx_t *)soft_aes_ctx->aes_cbc, 363 (char *)in_buf, out_len, &out); 364 365 if (rc != 0) 366 goto encrypt_failed; 367 368 if (update) { 369 /* 370 * For encrypt update, if there is remaining data, 371 * save it and its length in the context. 372 */ 373 if (remain != 0) 374 (void) memcpy(soft_aes_ctx->data, pData + 375 (ulDataLen - remain), remain); 376 soft_aes_ctx->remain_len = remain; 377 } else if (mechanism == CKM_AES_CBC_PAD) { 378 /* 379 * Save the remainder of the input 380 * block in a temporary block because 381 * we dont want to overrun the buffer 382 * by tacking on pad bytes. 383 */ 384 CK_BYTE tmpblock[AES_BLOCK_LEN]; 385 (void) memcpy(tmpblock, in_buf + out_len, 386 ulDataLen - out_len); 387 soft_add_pkcs7_padding(tmpblock + 388 (ulDataLen - out_len), 389 AES_BLOCK_LEN, ulDataLen - out_len); 390 391 out.cd_offset = out_len; 392 out.cd_length = AES_BLOCK_LEN; 393 out.cd_raw.iov_base = (char *)out_buf; 394 out.cd_raw.iov_len = out_len + AES_BLOCK_LEN; 395 396 /* Encrypt last block containing pad bytes. */ 397 rc = aes_encrypt_contiguous_blocks( 398 (aes_ctx_t *)soft_aes_ctx->aes_cbc, 399 (char *)tmpblock, AES_BLOCK_LEN, &out); 400 401 out_len += AES_BLOCK_LEN; 402 } 403 404 if (rc == 0) { 405 *pulEncryptedLen = out_len; 406 break; 407 } 408 encrypt_failed: 409 *pulEncryptedLen = 0; 410 rv = CKR_FUNCTION_FAILED; 411 goto cleanup; 412 } 413 case CKM_AES_CTR: 414 { 415 crypto_data_t out; 416 417 out.cd_format = CRYPTO_DATA_RAW; 418 out.cd_offset = 0; 419 out.cd_length = *pulEncryptedLen; 420 out.cd_raw.iov_base = (char *)pEncrypted; 421 out.cd_raw.iov_len = *pulEncryptedLen; 422 423 rc = aes_encrypt_contiguous_blocks(soft_aes_ctx->aes_cbc, 424 (char *)pData, ulDataLen, &out); 425 426 if (rc != 0) { 427 *pulEncryptedLen = 0; 428 rv = CKR_FUNCTION_FAILED; 429 goto cleanup; 430 } 431 /* 432 * Since AES counter mode is a stream cipher, we call 433 * aes_counter_final() to pick up any remaining bytes. 434 * It is an internal function that does not destroy 435 * the context like *normal* final routines. 436 */ 437 if (((aes_ctx_t *)soft_aes_ctx->aes_cbc)->ac_remainder_len > 0) 438 rc = ctr_mode_final(soft_aes_ctx->aes_cbc, &out, 439 aes_encrypt_block); 440 } 441 } /* end switch */ 442 443 if (update) 444 return (CKR_OK); 445 446 /* 447 * The following code will be executed if the caller is 448 * soft_encrypt() or an error occurred. The encryption 449 * operation will be terminated so we need to do some cleanup. 450 */ 451 cleanup: 452 (void) pthread_mutex_lock(&session_p->session_mutex); 453 aes_ctx = (aes_ctx_t *)soft_aes_ctx->aes_cbc; 454 if (aes_ctx != NULL) { 455 bzero(aes_ctx->ac_keysched, aes_ctx->ac_keysched_len); 456 free(soft_aes_ctx->aes_cbc); 457 } 458 459 bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len); 460 free(soft_aes_ctx->key_sched); 461 free(session_p->encrypt.context); 462 session_p->encrypt.context = NULL; 463 (void) pthread_mutex_unlock(&session_p->session_mutex); 464 465 return (rv); 466 } 467 468 469 /* 470 * soft_aes_decrypt_common() 471 * 472 * Arguments: 473 * session_p: pointer to soft_session_t struct 474 * pEncrypted: pointer to the input data to be decrypted 475 * ulEncryptedLen: length of the input data 476 * pData: pointer to the output data 477 * pulDataLen: pointer to the length of the output data 478 * Update: boolean flag indicates caller is soft_decrypt 479 * or soft_decrypt_update 480 * 481 * Description: 482 * This function calls the corresponding decrypt routine based 483 * on the mechanism. 484 * 485 * Returns: 486 * CKR_OK: success 487 * CKR_BUFFER_TOO_SMALL: the output buffer provided by application 488 * is too small 489 * CKR_ENCRYPTED_DATA_LEN_RANGE: the input data is not a multiple 490 * of blocksize 491 * CKR_FUNCTION_FAILED: decrypt function failed 492 */ 493 CK_RV 494 soft_aes_decrypt_common(soft_session_t *session_p, CK_BYTE_PTR pEncrypted, 495 CK_ULONG ulEncryptedLen, CK_BYTE_PTR pData, 496 CK_ULONG_PTR pulDataLen, boolean_t update) 497 { 498 499 int rc = 0; 500 CK_RV rv = CKR_OK; 501 soft_aes_ctx_t *soft_aes_ctx = 502 (soft_aes_ctx_t *)session_p->decrypt.context; 503 aes_ctx_t *aes_ctx; 504 CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism; 505 CK_BYTE *in_buf = NULL; 506 CK_BYTE *out_buf = NULL; 507 CK_ULONG out_len; 508 CK_ULONG total_len; 509 CK_ULONG remain; 510 511 if (mechanism == CKM_AES_CTR) 512 goto do_decryption; 513 514 /* 515 * AES only takes input length that is a multiple of 16 bytes 516 * for C_Decrypt function with the mechanism CKM_AES_ECB, 517 * CKM_AES_CBC or CKM_AES_CBC_PAD. 518 * 519 * AES allows any input length for C_DecryptUpdate function. 520 */ 521 if (!update) { 522 /* 523 * Called by C_Decrypt 524 */ 525 if ((ulEncryptedLen % AES_BLOCK_LEN) != 0) { 526 rv = CKR_ENCRYPTED_DATA_LEN_RANGE; 527 goto cleanup; 528 } 529 530 /* 531 * If application asks for the length of the output buffer 532 * to hold the plaintext? 533 */ 534 if (pData == NULL) { 535 *pulDataLen = ulEncryptedLen; 536 return (CKR_OK); 537 } 538 539 /* Is the application-supplied buffer large enough? */ 540 if (mechanism != CKM_AES_CBC_PAD) { 541 if (*pulDataLen < ulEncryptedLen) { 542 *pulDataLen = ulEncryptedLen; 543 return (CKR_BUFFER_TOO_SMALL); 544 } 545 out_len = ulEncryptedLen; 546 } else { 547 /* 548 * For CKM_AES_CBC_PAD, we don't know how 549 * many bytes for padding at this time, so 550 * we'd assume one block was padded. 551 */ 552 if (*pulDataLen < (ulEncryptedLen - AES_BLOCK_LEN)) { 553 *pulDataLen = ulEncryptedLen - AES_BLOCK_LEN; 554 return (CKR_BUFFER_TOO_SMALL); 555 } 556 out_len = ulEncryptedLen - AES_BLOCK_LEN; 557 } 558 in_buf = pEncrypted; 559 out_buf = pData; 560 } else { 561 /* 562 * Called by C_DecryptUpdate 563 * 564 * Add the lengths of last remaining data and current 565 * input data together to get the total input length. 566 */ 567 total_len = soft_aes_ctx->remain_len + ulEncryptedLen; 568 569 /* 570 * If the total input length is less than one blocksize, 571 * or if the total input length is just one blocksize and 572 * the mechanism is CKM_AES_CBC_PAD, we will need to delay 573 * decryption until when more data comes in next 574 * C_DecryptUpdate or when C_DecryptFinal is called. 575 */ 576 if ((total_len < AES_BLOCK_LEN) || 577 ((mechanism == CKM_AES_CBC_PAD) && 578 (total_len == AES_BLOCK_LEN))) { 579 if (pData != NULL) { 580 /* 581 * Save input data and its length in 582 * the remaining buffer of AES context. 583 */ 584 (void) memcpy(soft_aes_ctx->data + 585 soft_aes_ctx->remain_len, 586 pEncrypted, ulEncryptedLen); 587 soft_aes_ctx->remain_len += ulEncryptedLen; 588 } 589 590 /* Set output data length to 0. */ 591 *pulDataLen = 0; 592 return (CKR_OK); 593 } 594 595 /* Compute the length of remaing data. */ 596 remain = total_len % AES_BLOCK_LEN; 597 598 /* 599 * Make sure that the output length is a multiple of 600 * blocksize. 601 */ 602 out_len = total_len - remain; 603 604 if (mechanism == CKM_AES_CBC_PAD) { 605 /* 606 * If the input data length is a multiple of 607 * blocksize, then save the last block of input 608 * data in the remaining buffer. C_DecryptFinal 609 * will handle this last block of data. 610 */ 611 if (remain == 0) { 612 remain = AES_BLOCK_LEN; 613 out_len -= AES_BLOCK_LEN; 614 } 615 } 616 617 /* 618 * If application asks for the length of the output buffer 619 * to hold the plaintext? 620 */ 621 if (pData == NULL) { 622 *pulDataLen = out_len; 623 return (CKR_OK); 624 } 625 626 /* 627 * Is the application-supplied buffer large enough? 628 */ 629 if (*pulDataLen < out_len) { 630 *pulDataLen = out_len; 631 return (CKR_BUFFER_TOO_SMALL); 632 } 633 634 if (soft_aes_ctx->remain_len != 0) { 635 /* 636 * Copy last remaining data and current input data 637 * to the output buffer. 638 */ 639 (void) memmove(pData + soft_aes_ctx->remain_len, 640 pEncrypted, out_len - soft_aes_ctx->remain_len); 641 (void) memcpy(pData, soft_aes_ctx->data, 642 soft_aes_ctx->remain_len); 643 bzero(soft_aes_ctx->data, soft_aes_ctx->remain_len); 644 645 in_buf = pData; 646 } else { 647 in_buf = pEncrypted; 648 } 649 out_buf = pData; 650 } 651 652 do_decryption: 653 /* 654 * Begin Decryption. 655 */ 656 switch (mechanism) { 657 658 case CKM_AES_ECB: 659 { 660 661 ulong_t i; 662 uint8_t *tmp_inbuf; 663 uint8_t *tmp_outbuf; 664 665 for (i = 0; i < out_len; i += AES_BLOCK_LEN) { 666 tmp_inbuf = &in_buf[i]; 667 tmp_outbuf = &out_buf[i]; 668 /* Crunch one block of data for AES. */ 669 (void) aes_decrypt_block(soft_aes_ctx->key_sched, 670 tmp_inbuf, tmp_outbuf); 671 } 672 673 if (update) { 674 /* 675 * For decrypt update, if there is a remaining 676 * data, save it and its length in the context. 677 */ 678 if (remain != 0) 679 (void) memcpy(soft_aes_ctx->data, pEncrypted + 680 (ulEncryptedLen - remain), remain); 681 soft_aes_ctx->remain_len = remain; 682 } 683 684 *pulDataLen = out_len; 685 686 break; 687 } 688 689 case CKM_AES_CBC: 690 case CKM_AES_CBC_PAD: 691 { 692 crypto_data_t out; 693 CK_ULONG rem_len; 694 uint8_t last_block[AES_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 = aes_decrypt_contiguous_blocks( 704 (aes_ctx_t *)soft_aes_ctx->aes_cbc, 705 (char *)in_buf, out_len, &out); 706 707 if (rc != 0) 708 goto decrypt_failed; 709 710 if ((mechanism == CKM_AES_CBC_PAD) && (!update)) { 711 /* Decrypt last block containing pad bytes. */ 712 out.cd_offset = 0; 713 out.cd_length = AES_BLOCK_LEN; 714 out.cd_raw.iov_base = (char *)last_block; 715 out.cd_raw.iov_len = AES_BLOCK_LEN; 716 717 /* Decrypt last block containing pad bytes. */ 718 rc = aes_decrypt_contiguous_blocks( 719 (aes_ctx_t *)soft_aes_ctx->aes_cbc, 720 (char *)in_buf + out_len, AES_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 AES_BLOCK_LEN, &rem_len, AES_BLOCK_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_aes_ctx->data, pEncrypted + 752 (ulEncryptedLen - remain), remain); 753 soft_aes_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 case CKM_AES_CTR: 764 { 765 crypto_data_t out; 766 767 out.cd_format = CRYPTO_DATA_RAW; 768 out.cd_offset = 0; 769 out.cd_length = *pulDataLen; 770 out.cd_raw.iov_base = (char *)pData; 771 out.cd_raw.iov_len = *pulDataLen; 772 773 rc = aes_decrypt_contiguous_blocks(soft_aes_ctx->aes_cbc, 774 (char *)pEncrypted, ulEncryptedLen, &out); 775 776 if (rc != 0) { 777 *pulDataLen = 0; 778 rv = CKR_FUNCTION_FAILED; 779 goto cleanup; 780 } 781 782 /* 783 * Since AES counter mode is a stream cipher, we call 784 * aes_counter_final() to pick up any remaining bytes. 785 * It is an internal function that does not destroy 786 * the context like *normal* final routines. 787 */ 788 if (((aes_ctx_t *)soft_aes_ctx->aes_cbc)->ac_remainder_len 789 > 0) { 790 rc = ctr_mode_final(soft_aes_ctx->aes_cbc, &out, 791 aes_encrypt_block); 792 if (rc == CRYPTO_DATA_LEN_RANGE) 793 rc = CRYPTO_ENCRYPTED_DATA_LEN_RANGE; 794 } 795 } 796 } /* end switch */ 797 798 if (update) 799 return (CKR_OK); 800 801 /* 802 * The following code will be executed if the caller is 803 * soft_decrypt() or an error occurred. The decryption 804 * operation will be terminated so we need to do some cleanup. 805 */ 806 cleanup: 807 (void) pthread_mutex_lock(&session_p->session_mutex); 808 aes_ctx = (aes_ctx_t *)soft_aes_ctx->aes_cbc; 809 if (aes_ctx != NULL) { 810 bzero(aes_ctx->ac_keysched, aes_ctx->ac_keysched_len); 811 free(soft_aes_ctx->aes_cbc); 812 } 813 814 bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len); 815 free(soft_aes_ctx->key_sched); 816 free(session_p->decrypt.context); 817 session_p->decrypt.context = NULL; 818 (void) pthread_mutex_unlock(&session_p->session_mutex); 819 820 return (rv); 821 } 822 823 824 /* 825 * Allocate and initialize a context for AES CBC mode of operation. 826 */ 827 void * 828 aes_cbc_ctx_init(void *key_sched, size_t size, uint8_t *ivec) 829 { 830 831 cbc_ctx_t *cbc_ctx; 832 833 if ((cbc_ctx = calloc(1, sizeof (cbc_ctx_t))) == NULL) 834 return (NULL); 835 836 cbc_ctx->cc_keysched = key_sched; 837 cbc_ctx->cc_keysched_len = size; 838 839 (void) memcpy(&cbc_ctx->cc_iv[0], ivec, AES_BLOCK_LEN); 840 841 cbc_ctx->cc_lastp = (uint8_t *)cbc_ctx->cc_iv; 842 cbc_ctx->cc_flags |= CBC_MODE; 843 844 return (cbc_ctx); 845 } 846 847 /* 848 * Allocate and initialize a context for AES CTR mode of operation. 849 */ 850 void * 851 aes_ctr_ctx_init(void *key_sched, size_t size, uint8_t *param) 852 { 853 854 ctr_ctx_t *ctr_ctx; 855 CK_AES_CTR_PARAMS *pp; 856 857 /* LINTED: pointer alignment */ 858 pp = (CK_AES_CTR_PARAMS *)param; 859 860 if ((ctr_ctx = calloc(1, sizeof (ctr_ctx_t))) == NULL) 861 return (NULL); 862 863 ctr_ctx->ctr_keysched = key_sched; 864 ctr_ctx->ctr_keysched_len = size; 865 866 if (ctr_init_ctx(ctr_ctx, pp->ulCounterBits, pp->cb, aes_copy_block) 867 != CRYPTO_SUCCESS) { 868 free(ctr_ctx); 869 return (NULL); 870 } 871 872 return (ctr_ctx); 873 } 874