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