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