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