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