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