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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * Copyright (c) 2018, Joyent, Inc. 25 */ 26 27 #include <stdio.h> 28 #include <stdlib.h> 29 #include <strings.h> 30 #include <errno.h> 31 #include <security/cryptoki.h> 32 #include <cryptoutil.h> 33 #include "kernelGlobal.h" 34 #include "kernelObject.h" 35 #include "kernelSession.h" 36 #include "kernelSlot.h" 37 38 /* 39 * Add an object to the session's object list. 40 * 41 * This function will acquire the lock on the session, and release 42 * that lock after adding the object to the session's object list. 43 */ 44 void 45 kernel_add_object_to_session(kernel_object_t *objp, kernel_session_t *sp) 46 { 47 /* Acquire the session lock. */ 48 (void) pthread_mutex_lock(&sp->session_mutex); 49 50 /* Insert the new object in front of session's object list. */ 51 if (sp->object_list == NULL) { 52 sp->object_list = objp; 53 objp->next = NULL; 54 objp->prev = NULL; 55 } else { 56 sp->object_list->prev = objp; 57 objp->next = sp->object_list; 58 objp->prev = NULL; 59 sp->object_list = objp; 60 } 61 62 /* Release the session lock. */ 63 (void) pthread_mutex_unlock(&sp->session_mutex); 64 } 65 66 /* 67 * Clean up and release the storage allocated to the object. 68 * 69 * The function is called either with the object lock being held 70 * (by caller kernel_delete_object()), or there is no object lock 71 * yet (by kernel_build_XXX_object() during creating an object). 72 */ 73 void 74 kernel_cleanup_object(kernel_object_t *objp) 75 { 76 /* 77 * Free the storage allocated to a secret key object. 78 */ 79 if (objp->class == CKO_SECRET_KEY) { 80 if (OBJ_SEC(objp) != NULL && OBJ_SEC_VALUE(objp) != NULL) { 81 freezero(OBJ_SEC_VALUE(objp), OBJ_SEC_VALUE_LEN(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, boolean_t wrapper_only) 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 * Unless we are being forced to shut everything down, this only 417 * happens if the library's _fini() is running not if someone 418 * explicitly called C_Finalize(). 419 */ 420 if (wrapper_only) { 421 objp->obj_refcnt = 0; 422 } 423 424 while (objp->obj_refcnt != 0) { 425 /* 426 * We set the OBJECT_REFCNT_WAITING flag before we put 427 * this deleting thread in a wait state, so other non-deleting 428 * operation thread will signal to wake it up only when 429 * the object reference count becomes zero and this flag 430 * is set. 431 */ 432 objp->obj_delete_sync |= OBJECT_REFCNT_WAITING; 433 (void) pthread_cond_wait(&objp->obj_free_cond, 434 &objp->object_mutex); 435 } 436 437 objp->obj_delete_sync &= ~OBJECT_REFCNT_WAITING; 438 439 /* Mark object as no longer valid. */ 440 objp->magic_marker = 0; 441 442 (void) pthread_cond_destroy(&objp->obj_free_cond); 443 } 444 445 /* 446 * Delete a session object: 447 * - Remove the object from the session's object list. 448 * - Release the storage allocated to the object. 449 * 450 * The boolean argument ses_lock_held is used to indicate that whether 451 * the caller holds the session lock or not. 452 * - When called by kernel_delete_all_objects_in_session() or 453 * kernel_delete_pri_objects_in_slot() -- ses_lock_held = TRUE. 454 * 455 * The boolean argument wrapper_only is used to indicate that whether 456 * the caller only wants to clean up the object wrapper from the library and 457 * needs not to make an ioctl call. 458 * - This argument only applies to the object created in the provider level. 459 * - When called by kernel_cleanup_pri_objects_in_slot(), wrapper_only is TRUE. 460 * - When called by C_DestroyObject(), wrapper_only is FALSE. 461 * - When called by kernel_delete_all_objects_in_session(), the value of 462 * wrapper_only depends on its caller. 463 */ 464 CK_RV 465 kernel_delete_session_object(kernel_session_t *sp, kernel_object_t *objp, 466 boolean_t ses_lock_held, boolean_t wrapper_only) 467 { 468 CK_RV rv = CKR_OK; 469 crypto_object_destroy_t obj_destroy; 470 471 /* 472 * Check to see if the caller holds the lock on the session. 473 * If not, we need to acquire that lock in order to proceed. 474 */ 475 if (!ses_lock_held) { 476 /* Acquire the session lock. */ 477 (void) pthread_mutex_lock(&sp->session_mutex); 478 } 479 480 /* Remove the object from the session's object list first. */ 481 rv = kernel_remove_object_from_session(objp, sp); 482 if (!ses_lock_held) { 483 /* 484 * If the session lock is obtained by this function, 485 * then release that lock after removing the object 486 * from session's object list. 487 * We want the releasing of the object storage to 488 * be done without holding the session lock. 489 */ 490 (void) pthread_mutex_unlock(&sp->session_mutex); 491 } 492 493 if (rv != CKR_OK) 494 return (rv); 495 496 kernel_delete_object_cleanup(objp, wrapper_only); 497 498 /* Destroy the object. */ 499 if (objp->is_lib_obj) { 500 /* 501 * If this object is created in the library, cleanup the 502 * contents of this object such as free all the storage 503 * allocated for this object. 504 */ 505 kernel_cleanup_object(objp); 506 } else { 507 /* 508 * This object is created in the HW provider. If wrapper_only 509 * is FALSE, make an ioctl call to destroy it in kernel. 510 */ 511 if (!wrapper_only) { 512 obj_destroy.od_session = sp->k_session; 513 obj_destroy.od_handle = objp->k_handle; 514 515 while (ioctl(kernel_fd, CRYPTO_OBJECT_DESTROY, 516 &obj_destroy) < 0) { 517 if (errno != EINTR) 518 break; 519 } 520 521 /* 522 * Ignore ioctl return codes for a session object. 523 * If the kernel can not delete a session object, it 524 * is likely caused by the HW provider. There's not 525 * much that can be done. The library will still 526 * cleanup the object wrapper in the library. The HW 527 * provider will destroy all session objects when 528 * the application exits. 529 */ 530 } 531 } 532 533 /* Reset OBJECT_IS_DELETING flag. */ 534 objp->obj_delete_sync &= ~OBJECT_IS_DELETING; 535 536 (void) pthread_mutex_unlock(&objp->object_mutex); 537 /* Destroy the object lock */ 538 (void) pthread_mutex_destroy(&objp->object_mutex); 539 /* Free the object itself */ 540 kernel_object_delay_free(objp); 541 542 return (CKR_OK); 543 } 544 545 /* 546 * Delete all the objects in a session. The caller holds the lock 547 * on the session. If the wrapper_only argument is TRUE, the caller only 548 * want to clean up object wrappers in the library. 549 */ 550 void 551 kernel_delete_all_objects_in_session(kernel_session_t *sp, 552 boolean_t wrapper_only) 553 { 554 kernel_object_t *objp = sp->object_list; 555 kernel_object_t *objp1; 556 557 /* Delete all the objects in the session. */ 558 while (objp) { 559 objp1 = objp->next; 560 561 /* 562 * Delete an session object by calling 563 * kernel_delete_session_object(): 564 * - The 3rd TRUE boolean argument indicates that the caller 565 * holds the session lock. 566 * - The 4th boolean argument indicates whether we only want 567 * clean up object wrappers in the library. 568 */ 569 (void) kernel_delete_session_object(sp, objp, B_TRUE, 570 wrapper_only); 571 572 objp = objp1; 573 } 574 } 575 576 static CK_RV 577 add_to_search_result(kernel_object_t *obj, find_context_t *fcontext, 578 CK_ULONG *num_result_alloc) 579 { 580 /* 581 * allocate space for storing results if the currently 582 * allocated space is not enough 583 */ 584 if (*num_result_alloc <= fcontext->num_results) { 585 fcontext->objs_found = realloc(fcontext->objs_found, 586 sizeof (kernel_object_t *) * (*num_result_alloc + BUFSIZ)); 587 if (fcontext->objs_found == NULL) { 588 return (CKR_HOST_MEMORY); 589 } 590 *num_result_alloc += BUFSIZ; 591 } 592 593 (fcontext->objs_found)[(fcontext->num_results)++] = obj; 594 return (CKR_OK); 595 } 596 597 static CK_RV 598 search_for_objects(kernel_session_t *sp, CK_ATTRIBUTE_PTR pTemplate, 599 CK_ULONG ulCount, find_context_t *fcontext) 600 { 601 kernel_session_t *session_p; 602 kernel_object_t *obj; 603 CK_OBJECT_CLASS pclasses[6]; /* classes attrs possibly exist */ 604 CK_ULONG num_pclasses; /* number of possible classes */ 605 CK_ULONG num_result_alloc = 0; /* spaces allocated for results */ 606 CK_RV rv = CKR_OK; 607 kernel_slot_t *pslot; 608 609 if (ulCount > 0) { 610 /* there are some search requirement */ 611 kernel_process_find_attr(pclasses, &num_pclasses, 612 pTemplate, ulCount); 613 } 614 615 /* Acquire the slot lock */ 616 pslot = slot_table[sp->ses_slotid]; 617 (void) pthread_mutex_lock(&pslot->sl_mutex); 618 619 /* 620 * Go through all objects in each session. 621 * Acquire individual session lock for the session 622 * we are searching. 623 */ 624 session_p = pslot->sl_sess_list; 625 while (session_p) { 626 (void) pthread_mutex_lock(&session_p->session_mutex); 627 obj = session_p->object_list; 628 while (obj) { 629 (void) pthread_mutex_lock(&obj->object_mutex); 630 if (ulCount > 0) { 631 if (kernel_find_match_attrs(obj, pclasses, 632 num_pclasses, pTemplate, ulCount)) { 633 rv = add_to_search_result( 634 obj, fcontext, &num_result_alloc); 635 } 636 } else { 637 /* no search criteria, just record the object */ 638 rv = add_to_search_result(obj, fcontext, 639 &num_result_alloc); 640 } 641 (void) pthread_mutex_unlock(&obj->object_mutex); 642 if (rv != CKR_OK) { 643 (void) pthread_mutex_unlock( 644 &session_p->session_mutex); 645 goto cleanup; 646 } 647 obj = obj->next; 648 } 649 (void) pthread_mutex_unlock(&session_p->session_mutex); 650 session_p = session_p->next; 651 } 652 653 cleanup: 654 /* Release the slot lock */ 655 (void) pthread_mutex_unlock(&pslot->sl_mutex); 656 return (rv); 657 } 658 659 /* 660 * Initialize the context for C_FindObjects() calls 661 */ 662 CK_RV 663 kernel_find_objects_init(kernel_session_t *sp, CK_ATTRIBUTE_PTR pTemplate, 664 CK_ULONG ulCount) 665 { 666 CK_RV rv = CKR_OK; 667 CK_OBJECT_CLASS class; /* for kernel_validate_attr(). Value unused */ 668 find_context_t *fcontext; 669 670 if (ulCount) { 671 rv = kernel_validate_attr(pTemplate, ulCount, &class); 672 /* Make sure all attributes in template are valid */ 673 if (rv != CKR_OK) { 674 return (rv); 675 } 676 } 677 678 /* prepare the find context */ 679 fcontext = calloc(1, sizeof (find_context_t)); 680 if (fcontext == NULL) { 681 return (CKR_HOST_MEMORY); 682 } 683 684 rv = search_for_objects(sp, pTemplate, ulCount, fcontext); 685 if (rv != CKR_OK) { 686 free(fcontext); 687 return (rv); 688 } 689 690 /* store the find_context in the session */ 691 sp->find_objects.context = (CK_VOID_PTR)fcontext; 692 693 return (rv); 694 } 695 696 void 697 kernel_find_objects_final(kernel_session_t *sp) 698 { 699 find_context_t *fcontext; 700 701 fcontext = sp->find_objects.context; 702 sp->find_objects.context = NULL; 703 sp->find_objects.flags = 0; 704 if (fcontext->objs_found != NULL) { 705 free(fcontext->objs_found); 706 } 707 708 free(fcontext); 709 } 710 711 void 712 kernel_find_objects(kernel_session_t *sp, CK_OBJECT_HANDLE *obj_found, 713 CK_ULONG max_obj_requested, CK_ULONG *found_obj_count) 714 { 715 find_context_t *fcontext; 716 CK_ULONG num_obj_found = 0; 717 CK_ULONG i; 718 kernel_object_t *obj; 719 720 fcontext = sp->find_objects.context; 721 722 for (i = fcontext->next_result_index; 723 ((num_obj_found < max_obj_requested) && 724 (i < fcontext->num_results)); 725 i++) { 726 obj = fcontext->objs_found[i]; 727 if (obj != NULL) { 728 (void) pthread_mutex_lock(&obj->object_mutex); 729 /* a sanity check to make sure the obj is still valid */ 730 if (obj->magic_marker == KERNELTOKEN_OBJECT_MAGIC) { 731 obj_found[num_obj_found] = 732 (CK_OBJECT_HANDLE)obj; 733 num_obj_found++; 734 } 735 (void) pthread_mutex_unlock(&obj->object_mutex); 736 } 737 } 738 fcontext->next_result_index = i; 739 *found_obj_count = num_obj_found; 740 } 741 742 /* 743 * Add an token object to the token object list in slot. 744 * 745 * This function will acquire the lock on the slot, and release 746 * that lock after adding the object to the slot's token object list. 747 */ 748 void 749 kernel_add_token_object_to_slot(kernel_object_t *objp, kernel_slot_t *pslot) 750 { 751 /* Acquire the slot lock. */ 752 (void) pthread_mutex_lock(&pslot->sl_mutex); 753 754 /* Insert the new object in front of slot's token object list. */ 755 if (pslot->sl_tobj_list == NULL) { 756 pslot->sl_tobj_list = objp; 757 objp->next = NULL; 758 objp->prev = NULL; 759 } else { 760 pslot->sl_tobj_list->prev = objp; 761 objp->next = pslot->sl_tobj_list; 762 objp->prev = NULL; 763 pslot->sl_tobj_list = objp; 764 } 765 766 /* Release the slot lock. */ 767 (void) pthread_mutex_unlock(&pslot->sl_mutex); 768 } 769 770 /* 771 * Remove an token object from the slot's token object list. 772 * This routine is called by kernel_delete_token_object(). 773 * The caller of this function hold the slot lock. 774 */ 775 void 776 kernel_remove_token_object_from_slot(kernel_slot_t *pslot, 777 kernel_object_t *objp) 778 { 779 780 if (pslot->sl_tobj_list == objp) { 781 /* Object is the first one in the list */ 782 if (objp->next) { 783 pslot->sl_tobj_list = objp->next; 784 objp->next->prev = NULL; 785 } else { 786 /* Object is the only one in the list. */ 787 pslot->sl_tobj_list = NULL; 788 } 789 } else { 790 /* Object is not the first one in the list. */ 791 if (objp->next) { 792 /* Object is in the middle of the list. */ 793 objp->prev->next = objp->next; 794 objp->next->prev = objp->prev; 795 } else { 796 /* Object is the last one in the list. */ 797 objp->prev->next = NULL; 798 } 799 } 800 } 801 802 /* 803 * Delete a token object: 804 * - Remove the object from the slot's token object list. 805 * - Release the storage allocated to the object. 806 * 807 * The boolean argument slot_lock_held is used to indicate that whether 808 * the caller holds the slot lock or not. When the caller does not hold 809 * the slot lock, this function will acquire that lock in order to proceed, 810 * and also release that lock before returning to caller. 811 * 812 * The boolean argument wrapper_only is used to indicate that whether 813 * the caller only wants to the object wrapper from library. 814 */ 815 CK_RV 816 kernel_delete_token_object(kernel_slot_t *pslot, kernel_session_t *sp, 817 kernel_object_t *objp, boolean_t slot_lock_held, boolean_t wrapper_only) 818 { 819 CK_RV rv; 820 crypto_object_destroy_t obj_destroy; 821 int r; 822 823 /* 824 * Check to see if the caller holds the lock on the slot. 825 * If not, we need to acquire that lock in order to proceed. 826 */ 827 if (!slot_lock_held) { 828 (void) pthread_mutex_lock(&pslot->sl_mutex); 829 } 830 831 /* Remove the object from the slot's token object list first. */ 832 kernel_remove_token_object_from_slot(pslot, objp); 833 834 /* Release the slot lock if the call doesn't hold the lock. */ 835 if (!slot_lock_held) { 836 (void) pthread_mutex_unlock(&pslot->sl_mutex); 837 } 838 839 kernel_delete_object_cleanup(objp, wrapper_only); 840 841 if (!wrapper_only) { 842 obj_destroy.od_session = sp->k_session; 843 obj_destroy.od_handle = objp->k_handle; 844 845 while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_DESTROY, 846 &obj_destroy)) < 0) { 847 if (errno != EINTR) 848 break; 849 } 850 if (r < 0) { 851 rv = CKR_FUNCTION_FAILED; 852 } else { 853 rv = crypto2pkcs11_error_number( 854 obj_destroy.od_return_value); 855 } 856 857 /* 858 * Could not destroy an object from kernel. Write a warning 859 * in syslog, but we still clean up the object wrapper in 860 * the library. 861 */ 862 if (rv != CKR_OK) { 863 cryptoerror(LOG_ERR, "pkcs11_kernel: Could not " 864 "destroy an object in kernel."); 865 } 866 } 867 868 (void) pthread_mutex_unlock(&objp->object_mutex); 869 /* Destroy the object lock */ 870 (void) pthread_mutex_destroy(&objp->object_mutex); 871 /* Free the object itself */ 872 kernel_object_delay_free(objp); 873 874 return (CKR_OK); 875 } 876 877 /* 878 * Clean up private object wrappers in this slot. The caller holds the slot 879 * lock. 880 */ 881 void 882 kernel_cleanup_pri_objects_in_slot(kernel_slot_t *pslot, 883 kernel_session_t *cur_sp) 884 { 885 kernel_session_t *session_p; 886 kernel_object_t *objp; 887 kernel_object_t *objp1; 888 889 /* 890 * Delete every private token object from the slot' token object list 891 */ 892 objp = pslot->sl_tobj_list; 893 while (objp) { 894 objp1 = objp->next; 895 /* 896 * The first TRUE boolean argument indicates that the caller 897 * hold the slot lock. The second TRUE boolean argument 898 * indicates that the caller just wants to clean up the object 899 * wrapper from the library only. 900 */ 901 if (objp->bool_attr_mask & PRIVATE_BOOL_ON) { 902 (void) kernel_delete_token_object(pslot, cur_sp, objp, 903 B_TRUE, B_TRUE); 904 } 905 objp = objp1; 906 } 907 908 /* 909 * Walk through all the sessions in this slot and delete every 910 * private object. 911 */ 912 session_p = pslot->sl_sess_list; 913 while (session_p) { 914 915 /* Delete all the objects in the session. */ 916 objp = session_p->object_list; 917 while (objp) { 918 objp1 = objp->next; 919 /* 920 * The FALSE boolean argument indicates that the 921 * caller does not hold the session lock. The TRUE 922 * boolean argument indicates that the caller just 923 * want to clean upt the object wrapper from the 924 * library only. 925 */ 926 if (objp->bool_attr_mask & PRIVATE_BOOL_ON) { 927 (void) kernel_delete_session_object(session_p, 928 objp, B_FALSE, B_TRUE); 929 } 930 931 objp = objp1; 932 } 933 934 session_p = session_p->next; 935 } 936 } 937 938 /* 939 * Get the object size in bytes for the objects created in the library. 940 */ 941 CK_RV 942 kernel_get_object_size(kernel_object_t *obj, CK_ULONG_PTR pulSize) 943 { 944 CK_RV rv = CKR_OK; 945 CK_ULONG obj_size; 946 biginteger_t *big; 947 948 obj_size = sizeof (kernel_object_t); 949 950 switch (obj->class) { 951 case CKO_PUBLIC_KEY: 952 if (obj->key_type == CKK_RSA) { 953 big = OBJ_PUB_RSA_PUBEXPO(obj); 954 obj_size += big->big_value_len; 955 big = OBJ_PUB_RSA_MOD(obj); 956 obj_size += big->big_value_len; 957 958 } else if (obj->key_type == CKK_DSA) { 959 big = OBJ_PUB_DSA_PRIME(obj); 960 obj_size += big->big_value_len; 961 big = OBJ_PUB_DSA_SUBPRIME(obj); 962 obj_size += big->big_value_len; 963 big = OBJ_PUB_DSA_BASE(obj); 964 obj_size += big->big_value_len; 965 big = OBJ_PUB_DSA_VALUE(obj); 966 obj_size += big->big_value_len; 967 968 } else if (obj->key_type == CKK_EC) { 969 big = OBJ_PUB_EC_POINT(obj); 970 obj_size += big->big_value_len; 971 972 } else { 973 rv = CKR_OBJECT_HANDLE_INVALID; 974 } 975 break; 976 977 case CKO_PRIVATE_KEY: 978 if (obj->key_type == CKK_RSA) { 979 big = OBJ_PRI_RSA_MOD(obj); 980 obj_size += big->big_value_len; 981 982 big = OBJ_PRI_RSA_PUBEXPO(obj); /* optional */ 983 if (big != NULL) { 984 obj_size += big->big_value_len; 985 } 986 987 big = OBJ_PRI_RSA_PRIEXPO(obj); 988 obj_size += big->big_value_len; 989 990 big = OBJ_PRI_RSA_PRIME1(obj); /* optional */ 991 if (big != NULL) { 992 obj_size += big->big_value_len; 993 } 994 995 big = OBJ_PRI_RSA_PRIME2(obj); /* optional */ 996 if (big != NULL) { 997 obj_size += big->big_value_len; 998 } 999 1000 big = OBJ_PRI_RSA_EXPO1(obj); /* optional */ 1001 if (big != NULL) { 1002 obj_size += big->big_value_len; 1003 } 1004 1005 big = OBJ_PRI_RSA_EXPO2(obj); /* optional */ 1006 if (big != NULL) { 1007 obj_size += big->big_value_len; 1008 } 1009 1010 big = OBJ_PRI_RSA_COEF(obj); /* optional */ 1011 if (big != NULL) { 1012 obj_size += big->big_value_len; 1013 } 1014 1015 } else if (obj->key_type == CKK_DSA) { 1016 big = OBJ_PRI_DSA_PRIME(obj); 1017 obj_size += big->big_value_len; 1018 big = OBJ_PRI_DSA_SUBPRIME(obj); 1019 obj_size += big->big_value_len; 1020 big = OBJ_PRI_DSA_BASE(obj); 1021 obj_size += big->big_value_len; 1022 big = OBJ_PRI_DSA_VALUE(obj); 1023 obj_size += big->big_value_len; 1024 1025 } else if (obj->key_type == CKK_EC) { 1026 big = OBJ_PRI_EC_VALUE(obj); 1027 obj_size += big->big_value_len; 1028 1029 } else { 1030 rv = CKR_OBJECT_HANDLE_INVALID; 1031 } 1032 break; 1033 1034 case CKO_SECRET_KEY: 1035 obj_size += OBJ_SEC_VALUE_LEN(obj); 1036 break; 1037 1038 default: 1039 rv = CKR_OBJECT_HANDLE_INVALID; 1040 } 1041 1042 if (rv == CKR_OK) { 1043 *pulSize = obj_size; 1044 } 1045 1046 return (rv); 1047 } 1048 1049 /* 1050 * This function adds the to-be-freed session object to a linked list. 1051 * When the number of objects queued in the linked list reaches the 1052 * maximum threshold MAX_OBJ_TO_BE_FREED, it will free the first 1053 * object (FIFO) in the list. 1054 */ 1055 void 1056 kernel_object_delay_free(kernel_object_t *objp) 1057 { 1058 kernel_object_t *tmp; 1059 1060 (void) pthread_mutex_lock(&obj_delay_freed.obj_to_be_free_mutex); 1061 1062 /* Add the newly deleted object at the end of the list */ 1063 objp->next = NULL; 1064 if (obj_delay_freed.first == NULL) { 1065 obj_delay_freed.last = objp; 1066 obj_delay_freed.first = objp; 1067 } else { 1068 obj_delay_freed.last->next = objp; 1069 obj_delay_freed.last = objp; 1070 } 1071 1072 if (++obj_delay_freed.count >= MAX_OBJ_TO_BE_FREED) { 1073 /* 1074 * Free the first object in the list only if 1075 * the total count reaches maximum threshold. 1076 */ 1077 obj_delay_freed.count--; 1078 tmp = obj_delay_freed.first->next; 1079 free(obj_delay_freed.first); 1080 obj_delay_freed.first = tmp; 1081 } 1082 (void) pthread_mutex_unlock(&obj_delay_freed.obj_to_be_free_mutex); 1083 }