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