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 2005 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 <errno.h> 32 #include <security/cryptoki.h> 33 #include "kernelGlobal.h" 34 #include "kernelObject.h" 35 #include "kernelSession.h" 36 #include <errno.h> 37 #include <string.h> 38 #include <cryptoutil.h> 39 40 CK_RV 41 C_CreateObject(CK_SESSION_HANDLE hSession, 42 CK_ATTRIBUTE_PTR pTemplate, 43 CK_ULONG ulCount, 44 CK_OBJECT_HANDLE_PTR phObject) 45 { 46 47 CK_RV rv; 48 kernel_session_t *session_p; 49 boolean_t ses_lock_held = B_FALSE; 50 51 if (!kernel_initialized) 52 return (CKR_CRYPTOKI_NOT_INITIALIZED); 53 54 if ((pTemplate == NULL) || (ulCount == 0) || 55 (phObject == NULL)) { 56 return (CKR_ARGUMENTS_BAD); 57 } 58 59 /* 60 * Obtain the session pointer. Also, increment the session 61 * reference count. 62 */ 63 rv = handle2session(hSession, &session_p); 64 if (rv != CKR_OK) 65 return (rv); 66 67 /* Create a new object. */ 68 rv = kernel_add_object(pTemplate, ulCount, phObject, session_p); 69 70 /* 71 * Decrement the session reference count. 72 * We do not hold the session lock. 73 */ 74 REFRELE(session_p, ses_lock_held); 75 76 return (rv); 77 } 78 79 80 CK_RV 81 C_CopyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, 82 CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, 83 CK_OBJECT_HANDLE_PTR phNewObject) 84 { 85 86 CK_RV rv; 87 kernel_session_t *session_p; 88 boolean_t ses_lock_held = B_FALSE; 89 kernel_object_t *old_object; 90 kernel_object_t *new_object = NULL; 91 crypto_object_copy_t object_copy; 92 CK_BBOOL is_pri_obj = FALSE; 93 CK_BBOOL is_token_obj = FALSE; 94 kernel_slot_t *pslot; 95 int i, r; 96 97 if (!kernel_initialized) 98 return (CKR_CRYPTOKI_NOT_INITIALIZED); 99 100 /* Check arguments */ 101 if (((ulCount > 0) && (pTemplate == NULL)) || 102 (phNewObject == NULL)) { 103 return (CKR_ARGUMENTS_BAD); 104 } 105 106 /* 107 * Obtain the session pointer. Also, increment the session 108 * reference count. 109 */ 110 rv = handle2session(hSession, &session_p); 111 if (rv != CKR_OK) 112 return (rv); 113 114 /* Obtain the object pointer. */ 115 HANDLE2OBJECT(hObject, old_object, rv); 116 if (rv != CKR_OK) { 117 /* 118 * Decrement the session reference count. 119 * We do not hold the session lock. 120 */ 121 REFRELE(session_p, ses_lock_held); 122 return (rv); 123 } 124 125 (void) pthread_mutex_lock(&old_object->object_mutex); 126 127 if (old_object->is_lib_obj) { 128 /* 129 * Copy the old object to a new object. 130 * The 3rd argument with TRUE value indicates that 131 * everything in the object will be duplicated. 132 */ 133 rv = kernel_copy_object(old_object, &new_object, B_TRUE, 134 session_p); 135 136 if ((rv != CKR_OK) || (new_object == NULL)) { 137 /* Most likely we ran out of space. */ 138 (void) pthread_mutex_unlock(&old_object->object_mutex); 139 140 /* 141 * Decrement the session reference count. 142 * We do not hold the session lock. 143 */ 144 REFRELE(session_p, ses_lock_held); 145 return (rv); 146 } 147 148 new_object->is_lib_obj = B_TRUE; 149 /* No need to hold the lock on the old object. */ 150 (void) pthread_mutex_unlock(&old_object->object_mutex); 151 152 /* Modify the object attribute if requested */ 153 for (i = 0; i < ulCount; i++) { 154 /* Set the requested attribute into the new object. */ 155 rv = kernel_set_attribute(new_object, &pTemplate[i], 156 B_TRUE, session_p); 157 158 if (rv != CKR_OK) { 159 kernel_cleanup_object(new_object); 160 161 /* 162 * Decrement the session reference count. 163 * We do not hold the session lock. 164 */ 165 REFRELE(session_p, ses_lock_held); 166 return (rv); 167 } 168 } 169 170 /* Insert the new object into this session's object list. */ 171 kernel_add_object_to_session(new_object, session_p); 172 173 /* 174 * Decrement the session reference count. 175 * We do not hold the session lock. 176 */ 177 REFRELE(session_p, ses_lock_held); 178 179 /* set handle of the new object */ 180 *phNewObject = (CK_ULONG)new_object; 181 182 } else { 183 /* 184 * The old object was created in the HW provider. 185 * First, create an object wrapper in library. 186 */ 187 new_object = calloc(1, sizeof (kernel_object_t)); 188 if (new_object == NULL) { 189 rv = CKR_HOST_MEMORY; 190 goto failed_cleanup; 191 } 192 193 /* Call CRYPTO_OBJECT_COPY ioctl to get a new object. */ 194 object_copy.oc_session = session_p->k_session; 195 object_copy.oc_handle = old_object->k_handle; 196 object_copy.oc_count = ulCount; 197 object_copy.oc_new_attributes = NULL; 198 if (ulCount > 0) { 199 rv = process_object_attributes(pTemplate, ulCount, 200 &object_copy.oc_new_attributes, &is_token_obj); 201 if (rv != CKR_OK) { 202 goto failed_cleanup; 203 } 204 } 205 206 while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_COPY, 207 &object_copy)) < 0) { 208 if (errno != EINTR) 209 break; 210 } 211 if (r < 0) { 212 rv = CKR_FUNCTION_FAILED; 213 } else { 214 rv = crypto2pkcs11_error_number( 215 object_copy.oc_return_value); 216 } 217 218 /* Free the attributes' space allocated for ioctl */ 219 free_object_attributes(object_copy.oc_new_attributes, ulCount); 220 221 if (rv != CKR_OK) { 222 goto failed_cleanup; 223 } 224 225 /* No need to hold the lock on the old object. */ 226 (void) pthread_mutex_unlock(&old_object->object_mutex); 227 228 /* 229 * Store the kernel object handle in the object wrapper and 230 * get the CKA_PRIVATE value of the new object. 231 */ 232 new_object->k_handle = object_copy.oc_new_handle; 233 rv = get_cka_private_value(session_p, new_object->k_handle, 234 &is_pri_obj); 235 if (rv != CKR_OK) { 236 goto failed_cleanup; 237 } 238 239 /* 240 * Initialize other field of the object wrapper. 241 */ 242 new_object->is_lib_obj = B_FALSE; 243 new_object->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 244 new_object->session_handle = (CK_SESSION_HANDLE)session_p; 245 (void) pthread_mutex_init(&new_object->object_mutex, NULL); 246 247 if (is_pri_obj) 248 new_object->bool_attr_mask |= PRIVATE_BOOL_ON; 249 else 250 new_object->bool_attr_mask &= ~PRIVATE_BOOL_ON; 251 252 if (is_token_obj) 253 new_object->bool_attr_mask |= TOKEN_BOOL_ON; 254 else 255 new_object->bool_attr_mask &= ~TOKEN_BOOL_ON; 256 257 /* 258 * Add the new copied object into the slot's token list 259 * or the session list. We don't hold the slot lock. 260 */ 261 if (is_token_obj) { 262 pslot = slot_table[session_p->ses_slotid]; 263 264 /* 265 * Decrement the session reference count. 266 * We do not hold the session lock. 267 */ 268 REFRELE(session_p, ses_lock_held); 269 270 /* Add into the slot token object list. */ 271 kernel_add_token_object_to_slot(new_object, pslot); 272 } else { 273 kernel_add_object_to_session(new_object, session_p); 274 275 /* 276 * Decrement the session reference count. 277 * We do not hold the session lock. 278 */ 279 REFRELE(session_p, ses_lock_held); 280 } 281 282 /* set handle of the new object */ 283 *phNewObject = (CK_ULONG)new_object; 284 } 285 286 return (rv); 287 288 failed_cleanup: 289 (void) pthread_mutex_lock(&old_object->object_mutex); 290 291 if (new_object != NULL) { 292 (void) free(new_object); 293 } 294 295 REFRELE(session_p, ses_lock_held); 296 return (rv); 297 } 298 299 300 CK_RV 301 C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject) 302 { 303 CK_RV rv; 304 kernel_object_t *object_p; 305 kernel_session_t *session_p; 306 kernel_slot_t *pslot; 307 boolean_t ses_lock_held = B_FALSE; 308 CK_SESSION_HANDLE creating_session; 309 310 if (!kernel_initialized) 311 return (CKR_CRYPTOKI_NOT_INITIALIZED); 312 313 /* Obtain the session pointer. */ 314 rv = handle2session(hSession, &session_p); 315 if (rv != CKR_OK) 316 return (rv); 317 318 /* Obtain the object pointer. */ 319 HANDLE2OBJECT(hObject, object_p, rv); 320 if (rv != CKR_OK) { 321 goto clean_exit; 322 } 323 324 /* Only session objects can be destroyed at a read-only session. */ 325 if ((session_p->ses_RO) && 326 (object_p->bool_attr_mask & TOKEN_BOOL_ON)) { 327 rv = CKR_SESSION_READ_ONLY; 328 goto clean_exit; 329 } 330 331 /* 332 * If the object is a session object, obtain the session handle 333 * which object belongs to. For a token object, we will use the 334 * session handle from the caller, because the session used to 335 * create the token object may no longer exist. 336 */ 337 if (!(object_p->bool_attr_mask & TOKEN_BOOL_ON)) { 338 REFRELE(session_p, ses_lock_held); 339 creating_session = object_p->session_handle; 340 rv = handle2session(creating_session, &session_p); 341 if (rv != CKR_OK) 342 return (rv); 343 } 344 345 if (object_p->bool_attr_mask & TOKEN_BOOL_ON) { 346 /* 347 * The first FALSE boolean argument indicates that the caller 348 * does not hold the slot lock. The second FALSE boolean 349 * argument indicates that the caller wants to clean up the 350 * object in the HW provider also. 351 */ 352 pslot = slot_table[session_p->ses_slotid]; 353 rv = kernel_delete_token_object(pslot, session_p, object_p, 354 B_FALSE, B_FALSE); 355 } else { 356 /* 357 * The first FALSE boolean argument indicates that the caller 358 * does not hold the session lock. The second FALSE boolean 359 * argument indicates that the caller wants to clean the object 360 * in the HW provider also. 361 */ 362 rv = kernel_delete_session_object(session_p, object_p, B_FALSE, 363 B_FALSE); 364 } 365 366 clean_exit: 367 /* 368 * Decrement the session reference count. 369 * We do not hold the session lock. 370 */ 371 REFRELE(session_p, ses_lock_held); 372 return (rv); 373 } 374 375 376 CK_RV 377 C_GetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, 378 CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) 379 { 380 381 CK_RV rv = CKR_OK, rv1 = CKR_OK; 382 kernel_object_t *object_p; 383 kernel_session_t *session_p; 384 boolean_t ses_lock_held = B_FALSE; 385 crypto_object_get_attribute_value_t obj_get_attr; 386 int i, r; 387 388 if (!kernel_initialized) 389 return (CKR_CRYPTOKI_NOT_INITIALIZED); 390 391 if ((pTemplate == NULL) || (ulCount == 0)) 392 return (CKR_ARGUMENTS_BAD); 393 394 /* 395 * Obtain the session pointer. Also, increment the session 396 * reference count. 397 */ 398 rv = handle2session(hSession, &session_p); 399 if (rv != CKR_OK) 400 return (rv); 401 402 /* Obtain the object pointer. */ 403 HANDLE2OBJECT(hObject, object_p, rv); 404 if (rv != CKR_OK) { 405 /* 406 * Decrement the session reference count. 407 * We do not hold the session lock. 408 */ 409 REFRELE(session_p, ses_lock_held); 410 return (rv); 411 } 412 413 /* Acquire the lock on the object. */ 414 (void) pthread_mutex_lock(&object_p->object_mutex); 415 416 if (object_p->is_lib_obj) { 417 /* 418 * The object was created in the library. The library 419 * contains the value information of each attribute. 420 */ 421 for (i = 0; i < ulCount; i++) { 422 /* 423 * Get the value of each attribute in the template. 424 * (We must process EVERY attribute in the template.) 425 */ 426 rv = kernel_get_attribute(object_p, &pTemplate[i]); 427 if (rv != CKR_OK) 428 /* At least we catch some type of error. */ 429 rv1 = rv; 430 } 431 rv = rv1; 432 433 } else { 434 /* 435 * The object was created in HW provider, call ioctl to get 436 * the values of attributes. 437 */ 438 obj_get_attr.og_session = session_p->k_session; 439 obj_get_attr.og_handle = object_p->k_handle; 440 obj_get_attr.og_count = ulCount; 441 442 rv = process_object_attributes(pTemplate, ulCount, 443 &obj_get_attr.og_attributes, NULL); 444 if (rv != CKR_OK) { 445 goto clean_exit; 446 } 447 448 while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE, 449 &obj_get_attr)) < 0) { 450 if (errno != EINTR) 451 break; 452 } 453 if (r < 0) { 454 rv = CKR_FUNCTION_FAILED; 455 } else { 456 rv = crypto2pkcs11_error_number( 457 obj_get_attr.og_return_value); 458 } 459 460 /* 461 * The error codes CKR_ATTRIBUTE_SENSITIVE, 462 * CKR_ATTRIBUTE_TYPE_INVALID, and CKR_BUFFER_TOO_SMALL 463 * do not denote true errors for this function. If a call 464 * returns any of these three values, then the call must 465 * nonetheless have processed every attribute in the 466 * template. Every attribute in the template whose value 467 * can be returned will be returned. 468 */ 469 if ((rv == CKR_OK) || 470 (rv == CKR_ATTRIBUTE_SENSITIVE) || 471 (rv == CKR_ATTRIBUTE_TYPE_INVALID) || 472 (rv == CKR_BUFFER_TOO_SMALL)) { 473 rv1 = get_object_attributes(pTemplate, ulCount, 474 obj_get_attr.og_attributes); 475 if (rv1 != CKR_OK) { 476 rv = rv1; 477 } 478 } 479 480 /* Free the attributes' allocated for the ioctl call. */ 481 free_object_attributes(obj_get_attr.og_attributes, ulCount); 482 } 483 484 clean_exit: 485 486 /* Release the object lock */ 487 (void) pthread_mutex_unlock(&object_p->object_mutex); 488 489 /* 490 * Decrement the session reference count. 491 * We do not hold the session lock. 492 */ 493 REFRELE(session_p, ses_lock_held); 494 return (rv); 495 } 496 497 498 CK_RV 499 C_SetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, 500 CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) 501 { 502 CK_RV rv = CKR_OK; 503 kernel_object_t *object_p; 504 kernel_object_t *new_object = NULL; 505 kernel_session_t *session_p; 506 boolean_t ses_lock_held = B_FALSE; 507 crypto_object_set_attribute_value_t obj_set_attr; 508 int i, r; 509 510 if (!kernel_initialized) 511 return (CKR_CRYPTOKI_NOT_INITIALIZED); 512 513 if ((pTemplate == NULL) || (ulCount == 0)) 514 return (CKR_ARGUMENTS_BAD); 515 516 /* 517 * Obtain the session pointer. Also, increment the session 518 * reference count. 519 */ 520 rv = handle2session(hSession, &session_p); 521 if (rv != CKR_OK) 522 return (rv); 523 524 /* Obtain the object pointer. */ 525 HANDLE2OBJECT(hObject, object_p, rv); 526 if (rv != CKR_OK) { 527 /* 528 * Decrement the session reference count. 529 * We do not hold the session lock. 530 */ 531 REFRELE(session_p, ses_lock_held); 532 return (rv); 533 } 534 535 /* lock the object */ 536 (void) pthread_mutex_lock(&object_p->object_mutex); 537 538 /* 539 * If the object was created in the HW provider, changing its 540 * attributes' values need to be done in the provider too. 541 */ 542 if (!object_p->is_lib_obj) { 543 544 /* Cannot modify a token object with a READ-ONLY session */ 545 if (session_p->ses_RO && 546 (object_p->bool_attr_mask & TOKEN_BOOL_ON)) { 547 rv = CKR_SESSION_READ_ONLY; 548 (void) pthread_mutex_unlock(&object_p->object_mutex); 549 REFRELE(session_p, ses_lock_held); 550 return (rv); 551 } 552 553 obj_set_attr.sa_session = session_p->k_session; 554 obj_set_attr.sa_handle = object_p->k_handle; 555 obj_set_attr.sa_count = ulCount; 556 rv = process_object_attributes(pTemplate, ulCount, 557 &obj_set_attr.sa_attributes, NULL); 558 if (rv != CKR_OK) { 559 (void) pthread_mutex_unlock(&object_p->object_mutex); 560 REFRELE(session_p, ses_lock_held); 561 return (rv); 562 } 563 564 while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_SET_ATTRIBUTE_VALUE, 565 &obj_set_attr)) < 0) { 566 if (errno != EINTR) 567 break; 568 } 569 if (r < 0) { 570 rv = CKR_FUNCTION_FAILED; 571 } else { 572 rv = crypto2pkcs11_error_number( 573 obj_set_attr.sa_return_value); 574 } 575 576 /* Free the attributes' space allocated for the ioctl call. */ 577 free_object_attributes(obj_set_attr.sa_attributes, ulCount); 578 579 (void) pthread_mutex_unlock(&object_p->object_mutex); 580 REFRELE(session_p, ses_lock_held); 581 return (rv); 582 } 583 584 /* 585 * if we come here, the object must have been created in the 586 * library. The work will be done completely in the library. 587 * 588 * Copy the old object to a new object. We work on the copied 589 * version because in case of error we still keep the old one 590 * intact. 591 */ 592 rv = kernel_copy_object(object_p, &new_object, B_FALSE, NULL); 593 594 if ((rv != CKR_OK) || (new_object == NULL)) { 595 /* Most likely we ran out of space. */ 596 (void) pthread_mutex_unlock(&object_p->object_mutex); 597 598 /* 599 * Decrement the session reference count. 600 * We do not hold the session lock. 601 */ 602 REFRELE(session_p, ses_lock_held); 603 return (rv); 604 } 605 606 /* 607 * No need to hold the lock on the old object, because we 608 * will be working on the new scratch object. 609 */ 610 (void) pthread_mutex_unlock(&object_p->object_mutex); 611 612 for (i = 0; i < ulCount; i++) { 613 /* Set the requested attribute into the new object. */ 614 rv = kernel_set_attribute(new_object, &pTemplate[i], B_FALSE, 615 session_p); 616 617 if (rv != CKR_OK) { 618 kernel_cleanup_object(new_object); 619 free(new_object); 620 /* 621 * Decrement the session reference count. 622 * We do not hold the session lock. 623 */ 624 REFRELE(session_p, ses_lock_held); 625 return (rv); 626 } 627 } 628 629 /* 630 * We've successfully set all the requested attributes. 631 * Merge the new object with the old object, then destory 632 * the new one. The reason to do the merging is because we 633 * have to keep the original object handle (address of object). 634 */ 635 (void) pthread_mutex_lock(&object_p->object_mutex); 636 637 kernel_merge_object(object_p, new_object); 638 639 (void) pthread_mutex_unlock(&object_p->object_mutex); 640 free(new_object); 641 642 /* 643 * Decrement the session reference count. 644 * We do not hold the session lock. 645 */ 646 REFRELE(session_p, ses_lock_held); 647 648 return (rv); 649 } 650 651 652 CK_RV 653 C_GetObjectSize(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, 654 CK_ULONG_PTR pulSize) 655 { 656 657 CK_RV rv = CKR_OK; 658 kernel_object_t *object_p; 659 kernel_session_t *session_p; 660 boolean_t ses_lock_held = B_FALSE; 661 crypto_object_get_size_t obj_gs; 662 int r; 663 664 if (!kernel_initialized) 665 return (CKR_CRYPTOKI_NOT_INITIALIZED); 666 667 /* Check if pulSize is valid */ 668 if (pulSize == NULL) { 669 return (CKR_ARGUMENTS_BAD); 670 } 671 672 /* 673 * Obtain the session pointer. Also, increment the session 674 * reference count. 675 */ 676 rv = handle2session(hSession, &session_p); 677 if (rv != CKR_OK) 678 return (rv); 679 680 /* Obtain the object pointer. */ 681 HANDLE2OBJECT(hObject, object_p, rv); 682 if (rv != CKR_OK) { 683 /* 684 * Decrement the session reference count. 685 * We do not hold the session lock. 686 */ 687 REFRELE(session_p, ses_lock_held); 688 return (rv); 689 } 690 691 /* Acquire the lock on the object. */ 692 (void) pthread_mutex_lock(&object_p->object_mutex); 693 694 if (!object_p->is_lib_obj) { 695 /* 696 * The object was created in HW provider, call the 697 * CRYPTO_OBJECT_GET_SIZE ioctl. 698 */ 699 obj_gs.gs_session = session_p->k_session; 700 obj_gs.gs_handle = object_p->k_handle; 701 while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_GET_SIZE, 702 &obj_gs)) < 0) { 703 if (errno != EINTR) 704 break; 705 } 706 if (r < 0) { 707 rv = CKR_FUNCTION_FAILED; 708 } else { 709 rv = crypto2pkcs11_error_number( 710 obj_gs.gs_return_value); 711 } 712 713 if (rv == CKR_OK) { 714 *pulSize = obj_gs.gs_size; 715 } 716 717 } else { 718 rv = kernel_get_object_size(object_p, pulSize); 719 } 720 721 clean_exit: 722 723 /* Release the object lock */ 724 (void) pthread_mutex_unlock(&object_p->object_mutex); 725 726 /* 727 * Decrement the session reference count. 728 * We do not hold the session lock. 729 */ 730 REFRELE(session_p, ses_lock_held); 731 return (rv); 732 } 733 734 735 CK_RV 736 C_FindObjectsInit(CK_SESSION_HANDLE sh, CK_ATTRIBUTE_PTR pTemplate, 737 CK_ULONG ulCount) 738 { 739 CK_RV rv; 740 kernel_session_t *session_p; 741 boolean_t ses_lock_held = B_FALSE; 742 kernel_slot_t *pslot; 743 crypto_object_find_init_t obj_fi; 744 int r; 745 746 if (!kernel_initialized) 747 return (CKR_CRYPTOKI_NOT_INITIALIZED); 748 749 /* Check the arguments */ 750 if ((ulCount > 0) && (pTemplate == NULL)) { 751 return (CKR_ARGUMENTS_BAD); 752 } 753 754 /* 755 * Obtain the session pointer. Also, increment the session 756 * reference count. 757 */ 758 rv = handle2session(sh, &session_p); 759 if (rv != CKR_OK) 760 return (rv); 761 762 /* Acquire the session lock */ 763 (void) pthread_mutex_lock(&session_p->session_mutex); 764 ses_lock_held = B_TRUE; 765 766 /* Check to see if find operation is already active */ 767 if (session_p->find_objects.flags & CRYPTO_OPERATION_ACTIVE) { 768 /* decrement the session count, and unlock the mutex */ 769 REFRELE(session_p, ses_lock_held); 770 return (CKR_OPERATION_ACTIVE); 771 } else { 772 /* 773 * This active flag will remain ON until application calls 774 * C_FindObjectsFinal. 775 */ 776 session_p->find_objects.flags = CRYPTO_OPERATION_ACTIVE; 777 } 778 779 780 /* 781 * If the HW provider supports object creation, we call the 782 * CRYPTO_OBJECT_FIND_INIT ioctl to initialize object finding. 783 * Otherwise, all the objects are created in the library and we 784 * do the find objects solely in the library. 785 */ 786 pslot = slot_table[session_p->ses_slotid]; 787 if (pslot->sl_func_list.fl_object_create) { 788 obj_fi.fi_session = session_p->k_session; 789 (void) pthread_mutex_unlock(&session_p->session_mutex); 790 ses_lock_held = B_FALSE; 791 obj_fi.fi_count = ulCount; 792 rv = process_object_attributes(pTemplate, ulCount, 793 &obj_fi.fi_attributes, NULL); 794 if (rv == CKR_OK) { 795 while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_FIND_INIT, 796 &obj_fi)) < 0) { 797 if (errno != EINTR) 798 break; 799 } 800 if (r < 0) { 801 rv = CKR_FUNCTION_FAILED; 802 } else { 803 rv = crypto2pkcs11_error_number( 804 obj_fi.fi_return_value); 805 } 806 } 807 808 /* Free the attributes' space allocated for the ioctl call. */ 809 free_object_attributes(obj_fi.fi_attributes, ulCount); 810 811 } else { 812 (void) pthread_mutex_unlock(&session_p->session_mutex); 813 ses_lock_held = B_FALSE; 814 rv = kernel_find_objects_init(session_p, pTemplate, ulCount); 815 } 816 817 if (rv != CKR_OK) { 818 (void) pthread_mutex_lock(&session_p->session_mutex); 819 ses_lock_held = B_TRUE; 820 session_p->find_objects.flags = 0; 821 (void) pthread_mutex_unlock(&session_p->session_mutex); 822 ses_lock_held = B_FALSE; 823 } 824 825 /* decrement the session count, and unlock the mutex */ 826 REFRELE(session_p, ses_lock_held); 827 return (rv); 828 829 } 830 831 CK_RV 832 C_FindObjects(CK_SESSION_HANDLE sh, CK_OBJECT_HANDLE_PTR phObject, 833 CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount) 834 { 835 CK_RV rv = CKR_OK; 836 kernel_slot_t *pslot; 837 kernel_session_t *session_p; 838 boolean_t ses_lock_held = B_FALSE; 839 crypto_object_find_update_t obj_fu; 840 int r; 841 842 if (!kernel_initialized) 843 return (CKR_CRYPTOKI_NOT_INITIALIZED); 844 845 /* check for invalid arguments */ 846 if (((phObject == NULL) && (ulMaxObjectCount != 0)) || 847 (pulObjectCount == NULL)) { 848 return (CKR_ARGUMENTS_BAD); 849 } 850 851 if (ulMaxObjectCount == 0) { 852 /* don't need to do anything, just return */ 853 *pulObjectCount = 0; 854 return (CKR_OK); 855 } 856 857 /* 858 * Obtain the session pointer. Also, increment the session 859 * reference count. 860 */ 861 rv = handle2session(sh, &session_p); 862 if (rv != CKR_OK) 863 return (rv); 864 865 /* Acquire the slot lock */ 866 pslot = slot_table[session_p->ses_slotid]; 867 (void) pthread_mutex_lock(&pslot->sl_mutex); 868 869 /* Acquire the session lock */ 870 (void) pthread_mutex_lock(&session_p->session_mutex); 871 ses_lock_held = B_TRUE; 872 873 /* Check to see if find operation is active */ 874 if (!(session_p->find_objects.flags & CRYPTO_OPERATION_ACTIVE)) { 875 rv = CKR_OPERATION_NOT_INITIALIZED; 876 goto clean_exit; 877 } 878 879 /* 880 * Similar to C_FindObjectInit(), if the HW provider supports object 881 * creation, we call the respective ioctl to find objects. 882 * Otherwise, all the objects are created in the library and we do 883 * the find objects solely in the library. 884 */ 885 if (pslot->sl_func_list.fl_object_create) { 886 obj_fu.fu_session = session_p->k_session; 887 obj_fu.fu_max_count = ulMaxObjectCount; 888 obj_fu.fu_handles = (char *)calloc(1, 889 ulMaxObjectCount * sizeof (crypto_object_id_t)); 890 if (obj_fu.fu_handles == NULL) { 891 rv = CKR_HOST_MEMORY; 892 goto clean_exit; 893 } 894 895 while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_FIND_UPDATE, 896 &obj_fu)) < 0) { 897 if (errno != EINTR) 898 break; 899 } 900 if (r < 0) { 901 rv = CKR_FUNCTION_FAILED; 902 } else { 903 rv = crypto2pkcs11_error_number( 904 obj_fu.fu_return_value); 905 } 906 907 if (rv == CKR_OK) { 908 rv = process_found_objects(session_p, phObject, 909 pulObjectCount, obj_fu); 910 } 911 free(obj_fu.fu_handles); 912 913 } else { 914 915 kernel_find_objects(session_p, phObject, ulMaxObjectCount, 916 pulObjectCount); 917 rv = CKR_OK; 918 } 919 920 clean_exit: 921 /* decrement the session count, and release the session lock */ 922 REFRELE(session_p, ses_lock_held); 923 924 /* release the slot lock */ 925 (void) pthread_mutex_unlock(&pslot->sl_mutex); 926 927 return (rv); 928 } 929 930 931 CK_RV 932 C_FindObjectsFinal(CK_SESSION_HANDLE sh) 933 { 934 935 kernel_session_t *session_p; 936 CK_RV rv; 937 boolean_t ses_lock_held = B_FALSE; 938 kernel_slot_t *pslot; 939 crypto_object_find_final_t obj_ff; 940 int r; 941 942 if (!kernel_initialized) 943 return (CKR_CRYPTOKI_NOT_INITIALIZED); 944 945 /* 946 * Obtain the session pointer. Also, increment the session 947 * reference count. 948 */ 949 rv = handle2session(sh, &session_p); 950 if (rv != CKR_OK) 951 return (rv); 952 953 /* Acquire the session lock */ 954 (void) pthread_mutex_lock(&session_p->session_mutex); 955 ses_lock_held = B_TRUE; 956 957 /* Check to see if find operation is active */ 958 if (!(session_p->find_objects.flags & CRYPTO_OPERATION_ACTIVE)) { 959 REFRELE(session_p, ses_lock_held); 960 return (CKR_OPERATION_NOT_INITIALIZED); 961 } 962 963 /* 964 * Similar to C_FindObjectInit(), if the HW provider supports object 965 * creation, we need to call the CRYPTO_OBJECT_FIND_FINAL ioctl. 966 */ 967 pslot = slot_table[session_p->ses_slotid]; 968 if (pslot->sl_func_list.fl_object_create) { 969 obj_ff.ff_session = session_p->k_session; 970 while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_FIND_FINAL, 971 &obj_ff)) < 0) { 972 if (errno != EINTR) 973 break; 974 } 975 if (r < 0) { 976 rv = CKR_FUNCTION_FAILED; 977 } else { 978 rv = crypto2pkcs11_error_number( 979 obj_ff.ff_return_value); 980 } 981 982 /* only need to reset find_objects.flags */ 983 if (rv == CKR_OK) { 984 session_p->find_objects.flags = 0; 985 } 986 987 } else { 988 /* 989 * The find object operations were done in the library, we 990 * need to cleanup find_objects context. 991 */ 992 kernel_find_objects_final(session_p); 993 rv = CKR_OK; 994 } 995 996 /* decrement the session count, and release the lock */ 997 REFRELE(session_p, ses_lock_held); 998 return (rv); 999 } 1000