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 #include <pthread.h> 27 #include <stdlib.h> 28 #include <string.h> 29 #include <strings.h> 30 #include <sys/types.h> 31 #include <security/cryptoki.h> 32 #include "softSession.h" 33 #include "softObject.h" 34 #include "softCrypt.h" 35 #include <aes_impl.h> 36 37 /* 38 * Allocate context for the active encryption or decryption operation, and 39 * generate AES key schedule to speed up the operation. 40 */ 41 CK_RV 42 soft_aes_crypt_init_common(soft_session_t *session_p, 43 CK_MECHANISM_PTR pMechanism, soft_object_t *key_p, 44 boolean_t encrypt) 45 { 46 size_t size; 47 soft_aes_ctx_t *soft_aes_ctx; 48 49 soft_aes_ctx = calloc(1, sizeof (soft_aes_ctx_t)); 50 if (soft_aes_ctx == NULL) { 51 return (CKR_HOST_MEMORY); 52 } 53 54 soft_aes_ctx->key_sched = aes_alloc_keysched(&size, 0); 55 56 if (soft_aes_ctx->key_sched == NULL) { 57 free(soft_aes_ctx); 58 return (CKR_HOST_MEMORY); 59 } 60 61 soft_aes_ctx->keysched_len = size; 62 63 (void) pthread_mutex_lock(&session_p->session_mutex); 64 if (encrypt) { 65 /* Called by C_EncryptInit. */ 66 session_p->encrypt.context = soft_aes_ctx; 67 session_p->encrypt.mech.mechanism = pMechanism->mechanism; 68 } else { 69 /* Called by C_DecryptInit. */ 70 session_p->decrypt.context = soft_aes_ctx; 71 session_p->decrypt.mech.mechanism = pMechanism->mechanism; 72 } 73 (void) pthread_mutex_unlock(&session_p->session_mutex); 74 75 /* 76 * If this is a non-sensitive key and it does NOT have 77 * a key schedule yet, then allocate one and expand it. 78 * Otherwise, if it's a non-sensitive key, and it DOES have 79 * a key schedule already attached to it, just copy the 80 * pre-expanded schedule to the context and avoid the 81 * extra key schedule expansion operation. 82 */ 83 if (!(key_p->bool_attr_mask & SENSITIVE_BOOL_ON)) { 84 if (OBJ_KEY_SCHED(key_p) == NULL) { 85 void *ks; 86 87 (void) pthread_mutex_lock(&key_p->object_mutex); 88 if (OBJ_KEY_SCHED(key_p) == NULL) { 89 ks = aes_alloc_keysched(&size, 0); 90 if (ks == NULL) { 91 (void) pthread_mutex_unlock( 92 &key_p->object_mutex); 93 free(soft_aes_ctx); 94 return (CKR_HOST_MEMORY); 95 } 96 #ifdef __sparcv9 97 /* LINTED */ 98 aes_init_keysched(OBJ_SEC_VALUE(key_p), (uint_t) 99 (OBJ_SEC_VALUE_LEN(key_p) * 8), ks); 100 #else /* !__sparcv9 */ 101 aes_init_keysched(OBJ_SEC_VALUE(key_p), 102 (OBJ_SEC_VALUE_LEN(key_p) * 8), ks); 103 #endif /* __sparcv9 */ 104 OBJ_KEY_SCHED_LEN(key_p) = size; 105 OBJ_KEY_SCHED(key_p) = ks; 106 } 107 (void) pthread_mutex_unlock(&key_p->object_mutex); 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), soft_aes_ctx->key_sched); 121 #else /* !__sparcv9 */ 122 aes_init_keysched(OBJ_SEC_VALUE(key_p), 123 (OBJ_SEC_VALUE_LEN(key_p) * 8), soft_aes_ctx->key_sched); 124 #endif /* __sparcv9 */ 125 } 126 return (CKR_OK); 127 } 128 129 130 /* 131 * soft_aes_encrypt_common() 132 * 133 * Arguments: 134 * session_p: pointer to soft_session_t struct 135 * pData: pointer to the input data to be encrypted 136 * ulDataLen: length of the input data 137 * pEncrypted: pointer to the output data after encryption 138 * pulEncryptedLen: pointer to the length of the output data 139 * update: boolean flag indicates caller is soft_encrypt 140 * or soft_encrypt_update 141 * 142 * Description: 143 * This function calls the corresponding encrypt routine based 144 * on the mechanism. 145 * 146 * Returns: 147 * CKR_OK: success 148 * CKR_BUFFER_TOO_SMALL: the output buffer provided by application 149 * is too small 150 * CKR_FUNCTION_FAILED: encrypt function failed 151 * CKR_DATA_LEN_RANGE: the input data is not a multiple of blocksize 152 */ 153 CK_RV 154 soft_aes_encrypt_common(soft_session_t *session_p, CK_BYTE_PTR pData, 155 CK_ULONG ulDataLen, CK_BYTE_PTR pEncrypted, 156 CK_ULONG_PTR pulEncryptedLen, boolean_t update) 157 { 158 159 int rc = 0; 160 CK_RV rv = CKR_OK; 161 soft_aes_ctx_t *soft_aes_ctx = 162 (soft_aes_ctx_t *)session_p->encrypt.context; 163 aes_ctx_t *aes_ctx; 164 CK_MECHANISM_TYPE mechanism = session_p->encrypt.mech.mechanism; 165 CK_BYTE *in_buf = NULL; 166 CK_BYTE *out_buf = NULL; 167 CK_ULONG out_len; 168 CK_ULONG total_len; 169 CK_ULONG remain; 170 171 if (mechanism == CKM_AES_CTR) 172 goto do_encryption; 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 do_encryption: 311 /* 312 * Begin Encryption now. 313 */ 314 switch (mechanism) { 315 316 case CKM_AES_ECB: 317 { 318 319 ulong_t i; 320 uint8_t *tmp_inbuf; 321 uint8_t *tmp_outbuf; 322 323 for (i = 0; i < out_len; i += AES_BLOCK_LEN) { 324 tmp_inbuf = &in_buf[i]; 325 tmp_outbuf = &out_buf[i]; 326 /* Crunch one block of data for AES. */ 327 (void) aes_encrypt_block(soft_aes_ctx->key_sched, 328 tmp_inbuf, tmp_outbuf); 329 } 330 331 if (update) { 332 /* 333 * For encrypt update, if there is a remaining 334 * data, save it and its length in the context. 335 */ 336 if (remain != 0) 337 (void) memcpy(soft_aes_ctx->data, pData + 338 (ulDataLen - remain), remain); 339 soft_aes_ctx->remain_len = remain; 340 } 341 342 *pulEncryptedLen = out_len; 343 344 break; 345 } 346 347 case CKM_AES_CBC: 348 case CKM_AES_CBC_PAD: 349 { 350 crypto_data_t out; 351 352 out.cd_format = CRYPTO_DATA_RAW; 353 out.cd_offset = 0; 354 out.cd_length = out_len; 355 out.cd_raw.iov_base = (char *)out_buf; 356 out.cd_raw.iov_len = out_len; 357 358 /* Encrypt multiple blocks of data. */ 359 rc = aes_encrypt_contiguous_blocks( 360 (aes_ctx_t *)soft_aes_ctx->aes_cbc, 361 (char *)in_buf, out_len, &out); 362 363 if (rc != 0) 364 goto encrypt_failed; 365 366 if (update) { 367 /* 368 * For encrypt update, if there is remaining data, 369 * save it and its length in the context. 370 */ 371 if (remain != 0) 372 (void) memcpy(soft_aes_ctx->data, pData + 373 (ulDataLen - remain), remain); 374 soft_aes_ctx->remain_len = remain; 375 } else if (mechanism == CKM_AES_CBC_PAD) { 376 /* 377 * Save the remainder of the input 378 * block in a temporary block because 379 * we dont want to overrun the buffer 380 * by tacking on pad bytes. 381 */ 382 CK_BYTE tmpblock[AES_BLOCK_LEN]; 383 (void) memcpy(tmpblock, in_buf + out_len, 384 ulDataLen - out_len); 385 soft_add_pkcs7_padding(tmpblock + 386 (ulDataLen - out_len), 387 AES_BLOCK_LEN, ulDataLen - out_len); 388 389 out.cd_offset = out_len; 390 out.cd_length = AES_BLOCK_LEN; 391 out.cd_raw.iov_base = (char *)out_buf; 392 out.cd_raw.iov_len = out_len + AES_BLOCK_LEN; 393 394 /* Encrypt last block containing pad bytes. */ 395 rc = aes_encrypt_contiguous_blocks( 396 (aes_ctx_t *)soft_aes_ctx->aes_cbc, 397 (char *)tmpblock, AES_BLOCK_LEN, &out); 398 399 out_len += AES_BLOCK_LEN; 400 } 401 402 if (rc == 0) { 403 *pulEncryptedLen = out_len; 404 break; 405 } 406 encrypt_failed: 407 *pulEncryptedLen = 0; 408 rv = CKR_FUNCTION_FAILED; 409 goto cleanup; 410 } 411 case CKM_AES_CTR: 412 { 413 crypto_data_t out; 414 415 out.cd_format = CRYPTO_DATA_RAW; 416 out.cd_offset = 0; 417 out.cd_length = *pulEncryptedLen; 418 out.cd_raw.iov_base = (char *)pEncrypted; 419 out.cd_raw.iov_len = *pulEncryptedLen; 420 421 rc = aes_encrypt_contiguous_blocks(soft_aes_ctx->aes_cbc, 422 (char *)pData, ulDataLen, &out); 423 424 if (rc != 0) { 425 *pulEncryptedLen = 0; 426 rv = CKR_FUNCTION_FAILED; 427 goto cleanup; 428 } 429 /* 430 * Since AES counter mode is a stream cipher, we call 431 * aes_counter_final() to pick up any remaining bytes. 432 * It is an internal function that does not destroy 433 * the context like *normal* final routines. 434 */ 435 if (((aes_ctx_t *)soft_aes_ctx->aes_cbc)->ac_remainder_len > 0) 436 rc = ctr_mode_final(soft_aes_ctx->aes_cbc, &out, 437 aes_encrypt_block); 438 } 439 } /* end switch */ 440 441 if (update) 442 return (CKR_OK); 443 444 /* 445 * The following code will be executed if the caller is 446 * soft_encrypt() or an error occurred. The encryption 447 * operation will be terminated so we need to do some cleanup. 448 */ 449 cleanup: 450 (void) pthread_mutex_lock(&session_p->session_mutex); 451 aes_ctx = (aes_ctx_t *)soft_aes_ctx->aes_cbc; 452 if (aes_ctx != NULL) { 453 bzero(aes_ctx->ac_keysched, aes_ctx->ac_keysched_len); 454 free(soft_aes_ctx->aes_cbc); 455 } 456 457 bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len); 458 free(soft_aes_ctx->key_sched); 459 free(session_p->encrypt.context); 460 session_p->encrypt.context = NULL; 461 (void) pthread_mutex_unlock(&session_p->session_mutex); 462 463 return (rv); 464 } 465 466 467 /* 468 * soft_aes_decrypt_common() 469 * 470 * Arguments: 471 * session_p: pointer to soft_session_t struct 472 * pEncrypted: pointer to the input data to be decrypted 473 * ulEncryptedLen: length of the input data 474 * pData: pointer to the output data 475 * pulDataLen: pointer to the length of the output data 476 * Update: boolean flag indicates caller is soft_decrypt 477 * or soft_decrypt_update 478 * 479 * Description: 480 * This function calls the corresponding decrypt routine based 481 * on the mechanism. 482 * 483 * Returns: 484 * CKR_OK: success 485 * CKR_BUFFER_TOO_SMALL: the output buffer provided by application 486 * is too small 487 * CKR_ENCRYPTED_DATA_LEN_RANGE: the input data is not a multiple 488 * of blocksize 489 * CKR_FUNCTION_FAILED: decrypt function failed 490 */ 491 CK_RV 492 soft_aes_decrypt_common(soft_session_t *session_p, CK_BYTE_PTR pEncrypted, 493 CK_ULONG ulEncryptedLen, CK_BYTE_PTR pData, 494 CK_ULONG_PTR pulDataLen, boolean_t update) 495 { 496 497 int rc = 0; 498 CK_RV rv = CKR_OK; 499 soft_aes_ctx_t *soft_aes_ctx = 500 (soft_aes_ctx_t *)session_p->decrypt.context; 501 aes_ctx_t *aes_ctx; 502 CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism; 503 CK_BYTE *in_buf = NULL; 504 CK_BYTE *out_buf = NULL; 505 CK_ULONG out_len; 506 CK_ULONG total_len; 507 CK_ULONG remain; 508 509 if (mechanism == CKM_AES_CTR) 510 goto do_decryption; 511 512 /* 513 * AES only takes input length that is a multiple of 16 bytes 514 * for C_Decrypt function with the mechanism CKM_AES_ECB, 515 * CKM_AES_CBC or CKM_AES_CBC_PAD. 516 * 517 * AES allows any input length for C_DecryptUpdate function. 518 */ 519 if (!update) { 520 /* 521 * Called by C_Decrypt 522 */ 523 if ((ulEncryptedLen % AES_BLOCK_LEN) != 0) { 524 rv = CKR_ENCRYPTED_DATA_LEN_RANGE; 525 goto cleanup; 526 } 527 528 /* 529 * If application asks for the length of the output buffer 530 * to hold the plaintext? 531 */ 532 if (pData == NULL) { 533 *pulDataLen = ulEncryptedLen; 534 return (CKR_OK); 535 } 536 537 /* Is the application-supplied buffer large enough? */ 538 if (mechanism != CKM_AES_CBC_PAD) { 539 if (*pulDataLen < ulEncryptedLen) { 540 *pulDataLen = ulEncryptedLen; 541 return (CKR_BUFFER_TOO_SMALL); 542 } 543 out_len = ulEncryptedLen; 544 } else { 545 /* 546 * For CKM_AES_CBC_PAD, we don't know how 547 * many bytes for padding at this time, so 548 * we'd assume one block was padded. 549 */ 550 if (*pulDataLen < (ulEncryptedLen - AES_BLOCK_LEN)) { 551 *pulDataLen = ulEncryptedLen - AES_BLOCK_LEN; 552 return (CKR_BUFFER_TOO_SMALL); 553 } 554 out_len = ulEncryptedLen - AES_BLOCK_LEN; 555 } 556 in_buf = pEncrypted; 557 out_buf = pData; 558 } else { 559 /* 560 * Called by C_DecryptUpdate 561 * 562 * Add the lengths of last remaining data and current 563 * input data together to get the total input length. 564 */ 565 total_len = soft_aes_ctx->remain_len + ulEncryptedLen; 566 567 /* 568 * If the total input length is less than one blocksize, 569 * or if the total input length is just one blocksize and 570 * the mechanism is CKM_AES_CBC_PAD, we will need to delay 571 * decryption until when more data comes in next 572 * C_DecryptUpdate or when C_DecryptFinal is called. 573 */ 574 if ((total_len < AES_BLOCK_LEN) || 575 ((mechanism == CKM_AES_CBC_PAD) && 576 (total_len == AES_BLOCK_LEN))) { 577 if (pData != NULL) { 578 /* 579 * Save input data and its length in 580 * the remaining buffer of AES context. 581 */ 582 (void) memcpy(soft_aes_ctx->data + 583 soft_aes_ctx->remain_len, 584 pEncrypted, ulEncryptedLen); 585 soft_aes_ctx->remain_len += ulEncryptedLen; 586 } 587 588 /* Set output data length to 0. */ 589 *pulDataLen = 0; 590 return (CKR_OK); 591 } 592 593 /* Compute the length of remaing data. */ 594 remain = total_len % AES_BLOCK_LEN; 595 596 /* 597 * Make sure that the output length is a multiple of 598 * blocksize. 599 */ 600 out_len = total_len - remain; 601 602 if (mechanism == CKM_AES_CBC_PAD) { 603 /* 604 * If the input data length is a multiple of 605 * blocksize, then save the last block of input 606 * data in the remaining buffer. C_DecryptFinal 607 * will handle this last block of data. 608 */ 609 if (remain == 0) { 610 remain = AES_BLOCK_LEN; 611 out_len -= AES_BLOCK_LEN; 612 } 613 } 614 615 /* 616 * If application asks for the length of the output buffer 617 * to hold the plaintext? 618 */ 619 if (pData == NULL) { 620 *pulDataLen = out_len; 621 return (CKR_OK); 622 } 623 624 /* 625 * Is the application-supplied buffer large enough? 626 */ 627 if (*pulDataLen < out_len) { 628 *pulDataLen = out_len; 629 return (CKR_BUFFER_TOO_SMALL); 630 } 631 632 if (soft_aes_ctx->remain_len != 0) { 633 /* 634 * Copy last remaining data and current input data 635 * to the output buffer. 636 */ 637 (void) memmove(pData + soft_aes_ctx->remain_len, 638 pEncrypted, out_len - soft_aes_ctx->remain_len); 639 (void) memcpy(pData, soft_aes_ctx->data, 640 soft_aes_ctx->remain_len); 641 bzero(soft_aes_ctx->data, soft_aes_ctx->remain_len); 642 643 in_buf = pData; 644 } else { 645 in_buf = pEncrypted; 646 } 647 out_buf = pData; 648 } 649 650 do_decryption: 651 /* 652 * Begin Decryption. 653 */ 654 switch (mechanism) { 655 656 case CKM_AES_ECB: 657 { 658 659 ulong_t i; 660 uint8_t *tmp_inbuf; 661 uint8_t *tmp_outbuf; 662 663 for (i = 0; i < out_len; i += AES_BLOCK_LEN) { 664 tmp_inbuf = &in_buf[i]; 665 tmp_outbuf = &out_buf[i]; 666 /* Crunch one block of data for AES. */ 667 (void) aes_decrypt_block(soft_aes_ctx->key_sched, 668 tmp_inbuf, tmp_outbuf); 669 } 670 671 if (update) { 672 /* 673 * For decrypt update, if there is a remaining 674 * data, save it and its length in the context. 675 */ 676 if (remain != 0) 677 (void) memcpy(soft_aes_ctx->data, pEncrypted + 678 (ulEncryptedLen - remain), remain); 679 soft_aes_ctx->remain_len = remain; 680 } 681 682 *pulDataLen = out_len; 683 684 break; 685 } 686 687 case CKM_AES_CBC: 688 case CKM_AES_CBC_PAD: 689 { 690 crypto_data_t out; 691 CK_ULONG rem_len; 692 uint8_t last_block[AES_BLOCK_LEN]; 693 694 out.cd_format = CRYPTO_DATA_RAW; 695 out.cd_offset = 0; 696 out.cd_length = out_len; 697 out.cd_raw.iov_base = (char *)out_buf; 698 out.cd_raw.iov_len = out_len; 699 700 /* Decrypt multiple blocks of data. */ 701 rc = aes_decrypt_contiguous_blocks( 702 (aes_ctx_t *)soft_aes_ctx->aes_cbc, 703 (char *)in_buf, out_len, &out); 704 705 if (rc != 0) 706 goto decrypt_failed; 707 708 if ((mechanism == CKM_AES_CBC_PAD) && (!update)) { 709 /* Decrypt last block containing pad bytes. */ 710 out.cd_offset = 0; 711 out.cd_length = AES_BLOCK_LEN; 712 out.cd_raw.iov_base = (char *)last_block; 713 out.cd_raw.iov_len = AES_BLOCK_LEN; 714 715 /* Decrypt last block containing pad bytes. */ 716 rc = aes_decrypt_contiguous_blocks( 717 (aes_ctx_t *)soft_aes_ctx->aes_cbc, 718 (char *)in_buf + out_len, AES_BLOCK_LEN, &out); 719 720 if (rc != 0) 721 goto decrypt_failed; 722 723 /* 724 * Remove padding bytes after decryption of 725 * ciphertext block to produce the original 726 * plaintext. 727 */ 728 rv = soft_remove_pkcs7_padding(last_block, 729 AES_BLOCK_LEN, &rem_len, AES_BLOCK_LEN); 730 if (rv == CKR_OK) { 731 if (rem_len != 0) 732 (void) memcpy(out_buf + out_len, 733 last_block, rem_len); 734 *pulDataLen = out_len + rem_len; 735 } else { 736 *pulDataLen = 0; 737 goto cleanup; 738 } 739 } else { 740 *pulDataLen = out_len; 741 } 742 743 if (update) { 744 /* 745 * For decrypt update, if there is remaining data, 746 * save it and its length in the context. 747 */ 748 if (remain != 0) 749 (void) memcpy(soft_aes_ctx->data, pEncrypted + 750 (ulEncryptedLen - remain), remain); 751 soft_aes_ctx->remain_len = remain; 752 } 753 754 if (rc == 0) 755 break; 756 decrypt_failed: 757 *pulDataLen = 0; 758 rv = CKR_FUNCTION_FAILED; 759 goto cleanup; 760 } 761 case CKM_AES_CTR: 762 { 763 crypto_data_t out; 764 765 out.cd_format = CRYPTO_DATA_RAW; 766 out.cd_offset = 0; 767 out.cd_length = *pulDataLen; 768 out.cd_raw.iov_base = (char *)pData; 769 out.cd_raw.iov_len = *pulDataLen; 770 771 rc = aes_decrypt_contiguous_blocks(soft_aes_ctx->aes_cbc, 772 (char *)pEncrypted, ulEncryptedLen, &out); 773 774 if (rc != 0) { 775 *pulDataLen = 0; 776 rv = CKR_FUNCTION_FAILED; 777 goto cleanup; 778 } 779 780 /* 781 * Since AES counter mode is a stream cipher, we call 782 * aes_counter_final() to pick up any remaining bytes. 783 * It is an internal function that does not destroy 784 * the context like *normal* final routines. 785 */ 786 if (((aes_ctx_t *)soft_aes_ctx->aes_cbc)->ac_remainder_len 787 > 0) { 788 rc = ctr_mode_final(soft_aes_ctx->aes_cbc, &out, 789 aes_encrypt_block); 790 if (rc == CRYPTO_DATA_LEN_RANGE) 791 rc = CRYPTO_ENCRYPTED_DATA_LEN_RANGE; 792 } 793 } 794 } /* end switch */ 795 796 if (update) 797 return (CKR_OK); 798 799 /* 800 * The following code will be executed if the caller is 801 * soft_decrypt() or an error occurred. The decryption 802 * operation will be terminated so we need to do some cleanup. 803 */ 804 cleanup: 805 (void) pthread_mutex_lock(&session_p->session_mutex); 806 aes_ctx = (aes_ctx_t *)soft_aes_ctx->aes_cbc; 807 if (aes_ctx != NULL) { 808 bzero(aes_ctx->ac_keysched, aes_ctx->ac_keysched_len); 809 free(soft_aes_ctx->aes_cbc); 810 } 811 812 bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len); 813 free(soft_aes_ctx->key_sched); 814 free(session_p->decrypt.context); 815 session_p->decrypt.context = NULL; 816 (void) pthread_mutex_unlock(&session_p->session_mutex); 817 818 return (rv); 819 } 820 821 822 /* 823 * Allocate and initialize a context for AES CBC mode of operation. 824 */ 825 void * 826 aes_cbc_ctx_init(void *key_sched, size_t size, uint8_t *ivec) 827 { 828 829 cbc_ctx_t *cbc_ctx; 830 831 if ((cbc_ctx = calloc(1, sizeof (cbc_ctx_t))) == NULL) 832 return (NULL); 833 834 cbc_ctx->cbc_keysched = key_sched; 835 cbc_ctx->cbc_keysched_len = size; 836 837 (void) memcpy(&cbc_ctx->cbc_iv[0], ivec, AES_BLOCK_LEN); 838 839 cbc_ctx->cbc_lastp = (uint8_t *)cbc_ctx->cbc_iv; 840 cbc_ctx->cbc_flags |= CBC_MODE; 841 842 return (cbc_ctx); 843 } 844 845 /* 846 * Allocate and initialize a context for AES CTR mode of operation. 847 */ 848 void * 849 aes_ctr_ctx_init(void *key_sched, size_t size, uint8_t *param) 850 { 851 852 ctr_ctx_t *ctr_ctx; 853 CK_AES_CTR_PARAMS *pp; 854 855 /* LINTED: pointer alignment */ 856 pp = (CK_AES_CTR_PARAMS *)param; 857 858 if ((ctr_ctx = calloc(1, sizeof (ctr_ctx_t))) == NULL) 859 return (NULL); 860 861 ctr_ctx->ctr_keysched = key_sched; 862 ctr_ctx->ctr_keysched_len = size; 863 864 if (ctr_init_ctx(ctr_ctx, pp->ulCounterBits, pp->cb, aes_copy_block) 865 != CRYPTO_SUCCESS) { 866 free(ctr_ctx); 867 return (NULL); 868 } 869 870 return (ctr_ctx); 871 } 872