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 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <strings.h> 31 #include <errno.h> 32 #include <security/cryptoki.h> 33 #include <cryptoutil.h> 34 #include "kernelGlobal.h" 35 #include "kernelObject.h" 36 #include "kernelSession.h" 37 #include "kernelSlot.h" 38 39 /* 40 * Add an object to the session's object list. 41 * 42 * This function will acquire the lock on the session, and release 43 * that lock after adding the object to the session's object list. 44 */ 45 void 46 kernel_add_object_to_session(kernel_object_t *objp, kernel_session_t *sp) 47 { 48 /* Acquire the session lock. */ 49 (void) pthread_mutex_lock(&sp->session_mutex); 50 51 /* Insert the new object in front of session's object list. */ 52 if (sp->object_list == NULL) { 53 sp->object_list = objp; 54 objp->next = NULL; 55 objp->prev = NULL; 56 } else { 57 sp->object_list->prev = objp; 58 objp->next = sp->object_list; 59 objp->prev = NULL; 60 sp->object_list = objp; 61 } 62 63 /* Release the session lock. */ 64 (void) pthread_mutex_unlock(&sp->session_mutex); 65 } 66 67 /* 68 * Clean up and release the storage allocated to the object. 69 * 70 * The function is called either with the object lock being held 71 * (by caller kernel_delete_object()), or there is no object lock 72 * yet (by kernel_build_XXX_object() during creating an object). 73 */ 74 void 75 kernel_cleanup_object(kernel_object_t *objp) 76 { 77 /* 78 * Free the storage allocated to a secret key object. 79 */ 80 if (objp->class == CKO_SECRET_KEY) { 81 if (OBJ_SEC(objp) != NULL && OBJ_SEC_VALUE(objp) != NULL) { 82 bzero(OBJ_SEC_VALUE(objp), OBJ_SEC_VALUE_LEN(objp)); 83 free(OBJ_SEC_VALUE(objp)); 84 OBJ_SEC_VALUE(objp) = NULL; 85 OBJ_SEC_VALUE_LEN(objp) = 0; 86 } 87 free(OBJ_SEC(objp)); 88 OBJ_SEC(objp) = NULL; 89 } else { 90 kernel_cleanup_object_bigint_attrs(objp); 91 } 92 93 /* 94 * Free the storage allocated to the extra attribute list. 95 */ 96 kernel_cleanup_extra_attr(objp); 97 } 98 99 /* 100 * Create a new object. Copy the attributes that can be modified 101 * (in the boolean attribute mask field and extra attribute list) 102 * from the old object to the new object. 103 * 104 * The caller of this function holds the lock on the old object. 105 */ 106 CK_RV 107 kernel_copy_object(kernel_object_t *old_object, kernel_object_t **new_object, 108 boolean_t copy_everything, kernel_session_t *sp) 109 { 110 CK_RV rv = CKR_OK; 111 kernel_object_t *new_objp = NULL; 112 CK_ATTRIBUTE_INFO_PTR attrp; 113 114 /* Allocate new object. */ 115 new_objp = calloc(1, sizeof (kernel_object_t)); 116 if (new_objp == NULL) 117 return (CKR_HOST_MEMORY); 118 119 new_objp->class = old_object->class; 120 new_objp->bool_attr_mask = old_object->bool_attr_mask; 121 122 attrp = old_object->extra_attrlistp; 123 while (attrp) { 124 /* 125 * Copy the attribute_info struct from the old 126 * object to a new attribute_info struct, and add 127 * that new struct to the extra attribute list 128 * of the new object. 129 */ 130 rv = kernel_copy_extra_attr(attrp, new_objp); 131 if (rv != CKR_OK) { 132 kernel_cleanup_extra_attr(new_objp); 133 free(new_objp); 134 return (rv); 135 } 136 attrp = attrp->next; 137 } 138 139 *new_object = new_objp; 140 141 if (!copy_everything) { 142 /* done with copying all information that can be modified */ 143 return (CKR_OK); 144 } 145 146 /* 147 * Copy the rest of the object. 148 * Certain fields that are not appropriate for coping will be 149 * initialized. 150 */ 151 new_objp->key_type = old_object->key_type; 152 new_objp->magic_marker = old_object->magic_marker; 153 new_objp->mechanism = old_object->mechanism; 154 new_objp->session_handle = (CK_SESSION_HANDLE)sp; 155 (void) pthread_mutex_init(&(new_objp->object_mutex), NULL); 156 /* copy key related information */ 157 switch (new_objp->class) { 158 case CKO_PUBLIC_KEY: 159 rv = kernel_copy_public_key_attr(OBJ_PUB(old_object), 160 &(OBJ_PUB(new_objp)), new_objp->key_type); 161 break; 162 case CKO_PRIVATE_KEY: 163 rv = kernel_copy_private_key_attr(OBJ_PRI(old_object), 164 &(OBJ_PRI(new_objp)), new_objp->key_type); 165 break; 166 case CKO_SECRET_KEY: 167 rv = kernel_copy_secret_key_attr(OBJ_SEC(old_object), 168 &(OBJ_SEC(new_objp))); 169 break; 170 default: 171 /* should never be this case */ 172 break; 173 } 174 if (rv != CKR_OK) { 175 /* 176 * don't need to cleanup the memory from failure of copying 177 * any key related stuff. Each individual function for 178 * copying key attr will free the memory if it fails 179 */ 180 kernel_cleanup_extra_attr(new_objp); 181 free(new_objp); 182 } 183 return (rv); 184 } 185 186 /* 187 * Copy the attributes (in the boolean attribute mask field and 188 * extra attribute list) from the new object back to the original 189 * object. Also, clean up and release all the storage in the extra 190 * attribute list of the original object. 191 * 192 * The caller of this function holds the lock on the old object. 193 */ 194 void 195 kernel_merge_object(kernel_object_t *old_object, kernel_object_t *new_object) 196 { 197 198 old_object->bool_attr_mask = new_object->bool_attr_mask; 199 kernel_cleanup_extra_attr(old_object); 200 old_object->extra_attrlistp = new_object->extra_attrlistp; 201 202 } 203 204 /* 205 * Create a new object struct. If it is a session object, add the object to 206 * the session's object list. If it is a token object, add it to the slot's 207 * token object list. The caller does not hold the slot lock. 208 */ 209 CK_RV 210 kernel_add_object(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, 211 CK_ULONG *objecthandle_p, kernel_session_t *sp) 212 { 213 CK_RV rv = CKR_OK; 214 kernel_object_t *new_objp = NULL; 215 kernel_slot_t *pslot; 216 crypto_object_create_t objc; 217 CK_BBOOL is_pri_obj; 218 CK_BBOOL is_token_obj = B_FALSE; 219 int r; 220 221 new_objp = calloc(1, sizeof (kernel_object_t)); 222 if (new_objp == NULL) { 223 rv = CKR_HOST_MEMORY; 224 goto fail_cleanup; 225 } 226 227 new_objp->extra_attrlistp = NULL; 228 new_objp->is_lib_obj = B_TRUE; 229 230 /* 231 * If the HW provider supports object creation, create the object 232 * in the HW provider by calling the CRYPTO_OBJECT_CREATE ioctl. 233 * Otherwise, create the object in the library. 234 */ 235 pslot = slot_table[sp->ses_slotid]; 236 if (pslot->sl_func_list.fl_object_create) { 237 new_objp->is_lib_obj = B_FALSE; 238 objc.oc_session = sp->k_session; 239 objc.oc_count = ulCount; 240 rv = process_object_attributes(pTemplate, ulCount, 241 &objc.oc_attributes, &is_token_obj); 242 if (rv != CKR_OK) { 243 goto fail_cleanup; 244 } 245 246 /* Cannot create a token object with a READ-ONLY session */ 247 if (is_token_obj && sp->ses_RO) { 248 free_object_attributes(objc.oc_attributes, ulCount); 249 rv = CKR_SESSION_READ_ONLY; 250 goto fail_cleanup; 251 } 252 253 while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_CREATE, 254 &objc)) < 0) { 255 if (errno != EINTR) 256 break; 257 } 258 if (r < 0) { 259 rv = CKR_FUNCTION_FAILED; 260 } else { 261 rv = crypto2pkcs11_error_number(objc.oc_return_value); 262 } 263 264 free_object_attributes(objc.oc_attributes, ulCount); 265 266 if (rv != CKR_OK) { 267 goto fail_cleanup; 268 } 269 270 /* Get the CKA_PRIVATE value of this object. */ 271 new_objp->k_handle = objc.oc_handle; 272 rv = get_cka_private_value(sp, new_objp->k_handle, 273 &is_pri_obj); 274 if (rv != CKR_OK) { 275 goto fail_cleanup; 276 } 277 278 /* Set the PRIVATE_BOOL_ON and TOKEN_BOOL_ON attributes */ 279 if (is_pri_obj) 280 new_objp->bool_attr_mask |= PRIVATE_BOOL_ON; 281 else 282 new_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON; 283 284 if (is_token_obj) 285 new_objp->bool_attr_mask |= TOKEN_BOOL_ON; 286 else 287 new_objp->bool_attr_mask &= ~TOKEN_BOOL_ON; 288 289 } else { 290 /* 291 * Create the object in the library. 292 * Validate attribute template and fill in the attributes 293 * in the kernel_object_t. 294 */ 295 rv = kernel_build_object(pTemplate, ulCount, new_objp, sp, 296 KERNEL_CREATE_OBJ); 297 if (rv != CKR_OK) { 298 goto fail_cleanup; 299 } 300 } 301 302 /* Initialize the rest of stuffs in kernel_object_t. */ 303 (void) pthread_mutex_init(&new_objp->object_mutex, NULL); 304 new_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 305 new_objp->session_handle = (CK_SESSION_HANDLE)sp; 306 307 if (is_token_obj) { 308 /* Add the new object to the slot's token object list. */ 309 pslot = slot_table[sp->ses_slotid]; 310 kernel_add_token_object_to_slot(new_objp, pslot); 311 } else { 312 /* Add the new object to the session's object list. */ 313 kernel_add_object_to_session(new_objp, sp); 314 } 315 316 /* Type casting the address of an object struct to an object handle. */ 317 *objecthandle_p = (CK_ULONG)new_objp; 318 319 return (CKR_OK); 320 321 fail_cleanup: 322 if (new_objp) { 323 /* 324 * If the object is created in the HW provider, the storage 325 * allocated for the ioctl call is always cleaned up after 326 * the call. If the object is created in the library, 327 * the storage allocated inside of this object should 328 * have been cleaned up in the kernel_build_object() 329 * after an error occurred. Therefore, we can safely 330 * free the object. 331 */ 332 free(new_objp); 333 } 334 335 return (rv); 336 } 337 338 /* 339 * Remove an object from the session's object list. 340 * 341 * The caller of this function holds the session lock. 342 */ 343 CK_RV 344 kernel_remove_object_from_session(kernel_object_t *objp, kernel_session_t *sp) 345 { 346 kernel_object_t *tmp_objp; 347 boolean_t found = B_FALSE; 348 349 /* 350 * Remove the object from the session's object list. 351 */ 352 if ((sp == NULL) || 353 (sp->magic_marker != KERNELTOKEN_SESSION_MAGIC)) { 354 return (CKR_SESSION_HANDLE_INVALID); 355 } 356 357 if ((sp->object_list == NULL) || (objp == NULL) || 358 (objp->magic_marker != KERNELTOKEN_OBJECT_MAGIC)) { 359 return (CKR_OBJECT_HANDLE_INVALID); 360 } 361 362 tmp_objp = sp->object_list; 363 while (tmp_objp) { 364 if (tmp_objp == objp) { 365 found = B_TRUE; 366 break; 367 } 368 tmp_objp = tmp_objp->next; 369 } 370 if (!found) 371 return (CKR_OBJECT_HANDLE_INVALID); 372 373 if (sp->object_list == objp) { 374 /* Object is the first one in the list. */ 375 if (objp->next) { 376 sp->object_list = objp->next; 377 objp->next->prev = NULL; 378 } else { 379 /* Object is the only one in the list. */ 380 sp->object_list = NULL; 381 } 382 } else { 383 /* Object is not the first one in the list. */ 384 if (objp->next) { 385 /* Object is in the middle of the list. */ 386 objp->prev->next = objp->next; 387 objp->next->prev = objp->prev; 388 } else { 389 /* Object is the last one in the list. */ 390 objp->prev->next = NULL; 391 } 392 } 393 return (CKR_OK); 394 } 395 396 static void 397 kernel_delete_object_cleanup(kernel_object_t *objp) 398 { 399 /* Acquire the lock on the object. */ 400 (void) pthread_mutex_lock(&objp->object_mutex); 401 402 /* 403 * Make sure another thread hasn't freed the object. 404 */ 405 if (objp->magic_marker != KERNELTOKEN_OBJECT_MAGIC) { 406 (void) pthread_mutex_unlock(&objp->object_mutex); 407 return; 408 } 409 410 /* 411 * The deletion of an object must be blocked when the object 412 * reference count is not zero. This means if any object related 413 * operation starts prior to the delete object operation gets in, 414 * the object deleting thread must wait for the non-deleting 415 * operation to be completed before it can proceed the delete 416 * operation. 417 */ 418 while (objp->obj_refcnt != 0) { 419 /* 420 * We set the OBJECT_REFCNT_WAITING flag before we put 421 * this deleting thread in a wait state, so other non-deleting 422 * operation thread will signal to wake it up only when 423 * the object reference count becomes zero and this flag 424 * is set. 425 */ 426 objp->obj_delete_sync |= OBJECT_REFCNT_WAITING; 427 (void) pthread_cond_wait(&objp->obj_free_cond, 428 &objp->object_mutex); 429 } 430 431 objp->obj_delete_sync &= ~OBJECT_REFCNT_WAITING; 432 433 /* Mark object as no longer valid. */ 434 objp->magic_marker = 0; 435 436 (void) pthread_cond_destroy(&objp->obj_free_cond); 437 } 438 439 /* 440 * Delete a session object: 441 * - Remove the object from the session's object list. 442 * - Release the storage allocated to the object. 443 * 444 * The boolean argument ses_lock_held is used to indicate that whether 445 * the caller holds the session lock or not. 446 * - When called by kernel_delete_all_objects_in_session() or 447 * kernel_delete_pri_objects_in_slot() -- ses_lock_held = TRUE. 448 * 449 * The boolean argument wrapper_only is used to indicate that whether 450 * the caller only wants to clean up the object wrapper from the library and 451 * needs not to make an ioctl call. 452 * - This argument only applies to the object created in the provider level. 453 * - When called by kernel_cleanup_pri_objects_in_slot(), wrapper_only is TRUE. 454 * - When called by C_DestroyObject(), wrapper_only is FALSE. 455 * - When called by kernel_delete_all_objects_in_session(), the value of 456 * wrapper_only depends on its caller. 457 */ 458 CK_RV 459 kernel_delete_session_object(kernel_session_t *sp, kernel_object_t *objp, 460 boolean_t ses_lock_held, boolean_t wrapper_only) 461 { 462 CK_RV rv = CKR_OK; 463 crypto_object_destroy_t obj_destroy; 464 465 /* 466 * Check to see if the caller holds the lock on the session. 467 * If not, we need to acquire that lock in order to proceed. 468 */ 469 if (!ses_lock_held) { 470 /* Acquire the session lock. */ 471 (void) pthread_mutex_lock(&sp->session_mutex); 472 } 473 474 /* Remove the object from the session's object list first. */ 475 rv = kernel_remove_object_from_session(objp, sp); 476 if (!ses_lock_held) { 477 /* 478 * If the session lock is obtained by this function, 479 * then release that lock after removing the object 480 * from session's object list. 481 * We want the releasing of the object storage to 482 * be done without holding the session lock. 483 */ 484 (void) pthread_mutex_unlock(&sp->session_mutex); 485 } 486 487 if (rv != CKR_OK) 488 return (rv); 489 490 kernel_delete_object_cleanup(objp); 491 492 /* Destroy the object. */ 493 if (objp->is_lib_obj) { 494 /* 495 * If this object is created in the library, cleanup the 496 * contents of this object such as free all the storage 497 * allocated for this object. 498 */ 499 kernel_cleanup_object(objp); 500 } else { 501 /* 502 * This object is created in the HW provider. If wrapper_only 503 * is FALSE, make an ioctl call to destroy it in kernel. 504 */ 505 if (!wrapper_only) { 506 obj_destroy.od_session = sp->k_session; 507 obj_destroy.od_handle = objp->k_handle; 508 509 while (ioctl(kernel_fd, CRYPTO_OBJECT_DESTROY, 510 &obj_destroy) < 0) { 511 if (errno != EINTR) 512 break; 513 } 514 515 /* 516 * Ignore ioctl return codes for a session object. 517 * If the kernel can not delete a session object, it 518 * is likely caused by the HW provider. There's not 519 * much that can be done. The library will still 520 * cleanup the object wrapper in the library. The HW 521 * provider will destroy all session objects when 522 * the application exits. 523 */ 524 } 525 } 526 527 /* Reset OBJECT_IS_DELETING flag. */ 528 objp->obj_delete_sync &= ~OBJECT_IS_DELETING; 529 530 (void) pthread_mutex_unlock(&objp->object_mutex); 531 /* Destroy the object lock */ 532 (void) pthread_mutex_destroy(&objp->object_mutex); 533 /* Free the object itself */ 534 kernel_object_delay_free(objp); 535 536 return (CKR_OK); 537 } 538 539 /* 540 * Delete all the objects in a session. The caller holds the lock 541 * on the session. If the wrapper_only argument is TRUE, the caller only 542 * want to clean up object wrappers in the library. 543 */ 544 void 545 kernel_delete_all_objects_in_session(kernel_session_t *sp, 546 boolean_t wrapper_only) 547 { 548 kernel_object_t *objp = sp->object_list; 549 kernel_object_t *objp1; 550 551 /* Delete all the objects in the session. */ 552 while (objp) { 553 objp1 = objp->next; 554 555 /* 556 * Delete an session object by calling 557 * kernel_delete_session_object(): 558 * - The 3rd TRUE boolean argument indicates that the caller 559 * holds the session lock. 560 * - The 4th boolean argument indicates whether we only want 561 * clean up object wrappers in the library. 562 */ 563 (void) kernel_delete_session_object(sp, objp, B_TRUE, 564 wrapper_only); 565 566 objp = objp1; 567 } 568 } 569 570 static CK_RV 571 add_to_search_result(kernel_object_t *obj, find_context_t *fcontext, 572 CK_ULONG *num_result_alloc) 573 { 574 /* 575 * allocate space for storing results if the currently 576 * allocated space is not enough 577 */ 578 if (*num_result_alloc <= fcontext->num_results) { 579 fcontext->objs_found = realloc(fcontext->objs_found, 580 sizeof (kernel_object_t *) * (*num_result_alloc + BUFSIZ)); 581 if (fcontext->objs_found == NULL) { 582 return (CKR_HOST_MEMORY); 583 } 584 *num_result_alloc += BUFSIZ; 585 } 586 587 (fcontext->objs_found)[(fcontext->num_results)++] = obj; 588 return (CKR_OK); 589 } 590 591 static CK_RV 592 search_for_objects(kernel_session_t *sp, CK_ATTRIBUTE_PTR pTemplate, 593 CK_ULONG ulCount, find_context_t *fcontext) 594 { 595 kernel_session_t *session_p; 596 kernel_object_t *obj; 597 CK_OBJECT_CLASS pclasses[6]; /* classes attrs possiblely exist */ 598 CK_ULONG num_pclasses; /* number of possible classes */ 599 CK_ULONG num_result_alloc = 0; /* spaces allocated for results */ 600 CK_RV rv = CKR_OK; 601 kernel_slot_t *pslot; 602 603 if (ulCount > 0) { 604 /* there are some search requirement */ 605 kernel_process_find_attr(pclasses, &num_pclasses, 606 pTemplate, ulCount); 607 } 608 609 /* Acquire the slot lock */ 610 pslot = slot_table[sp->ses_slotid]; 611 (void) pthread_mutex_lock(&pslot->sl_mutex); 612 613 /* 614 * Go through all objects in each session. 615 * Acquire individual session lock for the session 616 * we are searching. 617 */ 618 session_p = pslot->sl_sess_list; 619 while (session_p) { 620 (void) pthread_mutex_lock(&session_p->session_mutex); 621 obj = session_p->object_list; 622 while (obj) { 623 (void) pthread_mutex_lock(&obj->object_mutex); 624 if (ulCount > 0) { 625 if (kernel_find_match_attrs(obj, pclasses, 626 num_pclasses, pTemplate, ulCount)) { 627 rv = add_to_search_result( 628 obj, fcontext, &num_result_alloc); 629 } 630 } else { 631 /* no search criteria, just record the object */ 632 rv = add_to_search_result(obj, fcontext, 633 &num_result_alloc); 634 } 635 (void) pthread_mutex_unlock(&obj->object_mutex); 636 if (rv != CKR_OK) { 637 (void) pthread_mutex_unlock( 638 &session_p->session_mutex); 639 goto cleanup; 640 } 641 obj = obj->next; 642 } 643 (void) pthread_mutex_unlock(&session_p->session_mutex); 644 session_p = session_p->next; 645 } 646 647 cleanup: 648 /* Release the slot lock */ 649 (void) pthread_mutex_unlock(&pslot->sl_mutex); 650 return (rv); 651 } 652 653 /* 654 * Initialize the context for C_FindObjects() calls 655 */ 656 CK_RV 657 kernel_find_objects_init(kernel_session_t *sp, CK_ATTRIBUTE_PTR pTemplate, 658 CK_ULONG ulCount) 659 { 660 CK_RV rv = CKR_OK; 661 CK_OBJECT_CLASS class; /* for kernel_validate_attr(). Value unused */ 662 find_context_t *fcontext; 663 664 if (ulCount) { 665 rv = kernel_validate_attr(pTemplate, ulCount, &class); 666 /* Make sure all attributes in template are valid */ 667 if (rv != CKR_OK) { 668 return (rv); 669 } 670 } 671 672 /* prepare the find context */ 673 fcontext = calloc(1, sizeof (find_context_t)); 674 if (fcontext == NULL) { 675 return (CKR_HOST_MEMORY); 676 } 677 678 rv = search_for_objects(sp, pTemplate, ulCount, fcontext); 679 if (rv != CKR_OK) { 680 free(fcontext); 681 return (rv); 682 } 683 684 /* store the find_context in the session */ 685 sp->find_objects.context = (CK_VOID_PTR)fcontext; 686 687 return (rv); 688 } 689 690 void 691 kernel_find_objects_final(kernel_session_t *sp) 692 { 693 find_context_t *fcontext; 694 695 fcontext = sp->find_objects.context; 696 sp->find_objects.context = NULL; 697 sp->find_objects.flags = 0; 698 if (fcontext->objs_found != NULL) { 699 free(fcontext->objs_found); 700 } 701 702 free(fcontext); 703 } 704 705 void 706 kernel_find_objects(kernel_session_t *sp, CK_OBJECT_HANDLE *obj_found, 707 CK_ULONG max_obj_requested, CK_ULONG *found_obj_count) 708 { 709 find_context_t *fcontext; 710 CK_ULONG num_obj_found = 0; 711 CK_ULONG i; 712 kernel_object_t *obj; 713 714 fcontext = sp->find_objects.context; 715 716 for (i = fcontext->next_result_index; 717 ((num_obj_found < max_obj_requested) && 718 (i < fcontext->num_results)); 719 i++) { 720 obj = fcontext->objs_found[i]; 721 if (obj != NULL) { 722 (void) pthread_mutex_lock(&obj->object_mutex); 723 /* a sanity check to make sure the obj is still valid */ 724 if (obj->magic_marker == KERNELTOKEN_OBJECT_MAGIC) { 725 obj_found[num_obj_found] = 726 (CK_OBJECT_HANDLE)obj; 727 num_obj_found++; 728 } 729 (void) pthread_mutex_unlock(&obj->object_mutex); 730 } 731 } 732 fcontext->next_result_index = i; 733 *found_obj_count = num_obj_found; 734 } 735 736 /* 737 * Add an token object to the token object list in slot. 738 * 739 * This function will acquire the lock on the slot, and release 740 * that lock after adding the object to the slot's token object list. 741 */ 742 void 743 kernel_add_token_object_to_slot(kernel_object_t *objp, kernel_slot_t *pslot) 744 { 745 /* Acquire the slot lock. */ 746 (void) pthread_mutex_lock(&pslot->sl_mutex); 747 748 /* Insert the new object in front of slot's token object list. */ 749 if (pslot->sl_tobj_list == NULL) { 750 pslot->sl_tobj_list = objp; 751 objp->next = NULL; 752 objp->prev = NULL; 753 } else { 754 pslot->sl_tobj_list->prev = objp; 755 objp->next = pslot->sl_tobj_list; 756 objp->prev = NULL; 757 pslot->sl_tobj_list = objp; 758 } 759 760 /* Release the slot lock. */ 761 (void) pthread_mutex_unlock(&pslot->sl_mutex); 762 } 763 764 /* 765 * Remove an token object from the slot's token object list. 766 * This routine is called by kernel_delete_token_object(). 767 * The caller of this function hold the slot lock. 768 */ 769 void 770 kernel_remove_token_object_from_slot(kernel_slot_t *pslot, 771 kernel_object_t *objp) 772 { 773 774 if (pslot->sl_tobj_list == objp) { 775 /* Object is the first one in the list */ 776 if (objp->next) { 777 pslot->sl_tobj_list = objp->next; 778 objp->next->prev = NULL; 779 } else { 780 /* Object is the only one in the list. */ 781 pslot->sl_tobj_list = NULL; 782 } 783 } else { 784 /* Object is not the first one in the list. */ 785 if (objp->next) { 786 /* Object is in the middle of the list. */ 787 objp->prev->next = objp->next; 788 objp->next->prev = objp->prev; 789 } else { 790 /* Object is the last one in the list. */ 791 objp->prev->next = NULL; 792 } 793 } 794 } 795 796 /* 797 * Delete a token object: 798 * - Remove the object from the slot's token object list. 799 * - Release the storage allocated to the object. 800 * 801 * The boolean argument slot_lock_held is used to indicate that whether 802 * the caller holds the slot lock or not. When the caller does not hold 803 * the slot lock, this function will acquire that lock in order to proceed, 804 * and also release that lock before returning to caller. 805 * 806 * The boolean argument wrapper_only is used to indicate that whether 807 * the caller only wants to the object wrapper from library. 808 */ 809 CK_RV 810 kernel_delete_token_object(kernel_slot_t *pslot, kernel_session_t *sp, 811 kernel_object_t *objp, boolean_t slot_lock_held, boolean_t wrapper_only) 812 { 813 CK_RV rv; 814 crypto_object_destroy_t obj_destroy; 815 int r; 816 817 /* 818 * Check to see if the caller holds the lock on the slot. 819 * If not, we need to acquire that lock in order to proceed. 820 */ 821 if (!slot_lock_held) { 822 (void) pthread_mutex_lock(&pslot->sl_mutex); 823 } 824 825 /* Remove the object from the slot's token object list first. */ 826 kernel_remove_token_object_from_slot(pslot, objp); 827 828 /* Release the slot lock if the call doesn't hold the lock. */ 829 if (!slot_lock_held) { 830 (void) pthread_mutex_unlock(&pslot->sl_mutex); 831 } 832 833 kernel_delete_object_cleanup(objp); 834 835 if (!wrapper_only) { 836 obj_destroy.od_session = sp->k_session; 837 obj_destroy.od_handle = objp->k_handle; 838 839 while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_DESTROY, 840 &obj_destroy)) < 0) { 841 if (errno != EINTR) 842 break; 843 } 844 if (r < 0) { 845 rv = CKR_FUNCTION_FAILED; 846 } else { 847 rv = crypto2pkcs11_error_number( 848 obj_destroy.od_return_value); 849 } 850 851 /* 852 * Could not destroy an object from kernel. Write a warning 853 * in syslog, but we still clean up the object wrapper in 854 * the library. 855 */ 856 if (rv != CKR_OK) { 857 cryptoerror(LOG_ERR, "pkcs11_kernel: Could not " 858 "destroy an object in kernel."); 859 } 860 } 861 862 (void) pthread_mutex_unlock(&objp->object_mutex); 863 /* Destroy the object lock */ 864 (void) pthread_mutex_destroy(&objp->object_mutex); 865 /* Free the object itself */ 866 kernel_object_delay_free(objp); 867 868 return (CKR_OK); 869 } 870 871 /* 872 * Clean up private object wrappers in this slot. The caller holds the slot 873 * lock. 874 */ 875 void 876 kernel_cleanup_pri_objects_in_slot(kernel_slot_t *pslot, 877 kernel_session_t *cur_sp) 878 { 879 kernel_session_t *session_p; 880 kernel_object_t *objp; 881 kernel_object_t *objp1; 882 883 /* 884 * Delete every private token object from the slot' token object list 885 */ 886 objp = pslot->sl_tobj_list; 887 while (objp) { 888 objp1 = objp->next; 889 /* 890 * The first TRUE boolean argument indicates that the caller 891 * hold the slot lock. The second TRUE boolean argument 892 * indicates that the caller just wants to clean up the object 893 * wrapper from the library only. 894 */ 895 if (objp->bool_attr_mask & PRIVATE_BOOL_ON) { 896 (void) kernel_delete_token_object(pslot, cur_sp, objp, 897 B_TRUE, B_TRUE); 898 } 899 objp = objp1; 900 } 901 902 /* 903 * Walk through all the sessions in this slot and delete every 904 * private object. 905 */ 906 session_p = pslot->sl_sess_list; 907 while (session_p) { 908 909 /* Delete all the objects in the session. */ 910 objp = session_p->object_list; 911 while (objp) { 912 objp1 = objp->next; 913 /* 914 * The FALSE boolean argument indicates that the 915 * caller does not hold the session lock. The TRUE 916 * boolean argument indicates that the caller just 917 * want to clean upt the object wrapper from the 918 * library only. 919 */ 920 if (objp->bool_attr_mask & PRIVATE_BOOL_ON) { 921 (void) kernel_delete_session_object(session_p, 922 objp, B_FALSE, B_TRUE); 923 } 924 925 objp = objp1; 926 } 927 928 session_p = session_p->next; 929 } 930 } 931 932 /* 933 * Get the object size in bytes for the objects created in the library. 934 */ 935 CK_RV 936 kernel_get_object_size(kernel_object_t *obj, CK_ULONG_PTR pulSize) 937 { 938 CK_RV rv = CKR_OK; 939 CK_ULONG obj_size; 940 biginteger_t *big; 941 942 obj_size = sizeof (kernel_object_t); 943 944 switch (obj->class) { 945 case CKO_PUBLIC_KEY: 946 if (obj->key_type == CKK_RSA) { 947 big = OBJ_PUB_RSA_PUBEXPO(obj); 948 obj_size += big->big_value_len; 949 big = OBJ_PUB_RSA_MOD(obj); 950 obj_size += big->big_value_len; 951 952 } else if (obj->key_type == CKK_DSA) { 953 big = OBJ_PUB_DSA_PRIME(obj); 954 obj_size += big->big_value_len; 955 big = OBJ_PUB_DSA_SUBPRIME(obj); 956 obj_size += big->big_value_len; 957 big = OBJ_PUB_DSA_BASE(obj); 958 obj_size += big->big_value_len; 959 big = OBJ_PUB_DSA_VALUE(obj); 960 obj_size += big->big_value_len; 961 962 } else if (obj->key_type == CKK_EC) { 963 big = OBJ_PUB_EC_POINT(obj); 964 obj_size += big->big_value_len; 965 966 } else { 967 rv = CKR_OBJECT_HANDLE_INVALID; 968 } 969 break; 970 971 case CKO_PRIVATE_KEY: 972 if (obj->key_type == CKK_RSA) { 973 big = OBJ_PRI_RSA_MOD(obj); 974 obj_size += big->big_value_len; 975 976 big = OBJ_PRI_RSA_PUBEXPO(obj); /* optional */ 977 if (big != NULL) { 978 obj_size += big->big_value_len; 979 } 980 981 big = OBJ_PRI_RSA_PRIEXPO(obj); 982 obj_size += big->big_value_len; 983 984 big = OBJ_PRI_RSA_PRIME1(obj); /* optional */ 985 if (big != NULL) { 986 obj_size += big->big_value_len; 987 } 988 989 big = OBJ_PRI_RSA_PRIME2(obj); /* optional */ 990 if (big != NULL) { 991 obj_size += big->big_value_len; 992 } 993 994 big = OBJ_PRI_RSA_EXPO1(obj); /* optional */ 995 if (big != NULL) { 996 obj_size += big->big_value_len; 997 } 998 999 big = OBJ_PRI_RSA_EXPO2(obj); /* optional */ 1000 if (big != NULL) { 1001 obj_size += big->big_value_len; 1002 } 1003 1004 big = OBJ_PRI_RSA_COEF(obj); /* optional */ 1005 if (big != NULL) { 1006 obj_size += big->big_value_len; 1007 } 1008 1009 } else if (obj->key_type == CKK_DSA) { 1010 big = OBJ_PRI_DSA_PRIME(obj); 1011 obj_size += big->big_value_len; 1012 big = OBJ_PRI_DSA_SUBPRIME(obj); 1013 obj_size += big->big_value_len; 1014 big = OBJ_PRI_DSA_BASE(obj); 1015 obj_size += big->big_value_len; 1016 big = OBJ_PRI_DSA_VALUE(obj); 1017 obj_size += big->big_value_len; 1018 1019 } else if (obj->key_type == CKK_EC) { 1020 big = OBJ_PRI_EC_VALUE(obj); 1021 obj_size += big->big_value_len; 1022 1023 } else { 1024 rv = CKR_OBJECT_HANDLE_INVALID; 1025 } 1026 break; 1027 1028 case CKO_SECRET_KEY: 1029 obj_size += OBJ_SEC_VALUE_LEN(obj); 1030 break; 1031 1032 default: 1033 rv = CKR_OBJECT_HANDLE_INVALID; 1034 } 1035 1036 if (rv == CKR_OK) { 1037 *pulSize = obj_size; 1038 } 1039 1040 return (rv); 1041 } 1042 1043 /* 1044 * This function adds the to-be-freed session object to a linked list. 1045 * When the number of objects queued in the linked list reaches the 1046 * maximum threshold MAX_OBJ_TO_BE_FREED, it will free the first 1047 * object (FIFO) in the list. 1048 */ 1049 void 1050 kernel_object_delay_free(kernel_object_t *objp) 1051 { 1052 kernel_object_t *tmp; 1053 1054 (void) pthread_mutex_lock(&obj_delay_freed.obj_to_be_free_mutex); 1055 1056 /* Add the newly deleted object at the end of the list */ 1057 objp->next = NULL; 1058 if (obj_delay_freed.first == NULL) { 1059 obj_delay_freed.last = objp; 1060 obj_delay_freed.first = objp; 1061 } else { 1062 obj_delay_freed.last->next = objp; 1063 obj_delay_freed.last = objp; 1064 } 1065 1066 if (++obj_delay_freed.count >= MAX_OBJ_TO_BE_FREED) { 1067 /* 1068 * Free the first object in the list only if 1069 * the total count reaches maximum threshold. 1070 */ 1071 obj_delay_freed.count--; 1072 tmp = obj_delay_freed.first->next; 1073 free(obj_delay_freed.first); 1074 obj_delay_freed.first = tmp; 1075 } 1076 (void) pthread_mutex_unlock(&obj_delay_freed.obj_to_be_free_mutex); 1077 } 1078