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