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