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 /* 23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 24 * Copyright 2020 Joyent, Inc. 25 */ 26 27 #include <pthread.h> 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <string.h> 31 #include <security/cryptoki.h> 32 #include <sys/debug.h> 33 #include "softGlobal.h" 34 #include "softObject.h" 35 #include "softSession.h" 36 #include "softKeystore.h" 37 #include "softKeystoreUtil.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 soft_add_object_to_session(soft_object_t *objp, soft_session_t *sp) 47 { 48 49 /* Acquire the session lock. */ 50 (void) pthread_mutex_lock(&sp->session_mutex); 51 52 /* Insert the new object in front of session's object list. */ 53 if (sp->object_list == NULL) { 54 sp->object_list = objp; 55 objp->next = NULL; 56 objp->prev = NULL; 57 } else { 58 sp->object_list->prev = objp; 59 objp->next = sp->object_list; 60 objp->prev = NULL; 61 sp->object_list = objp; 62 } 63 64 /* Release the session lock. */ 65 (void) pthread_mutex_unlock(&sp->session_mutex); 66 } 67 68 69 /* 70 * Clean up and release the storage allocated to the object. 71 * 72 * The function is called either with the object lock being held 73 * (by caller soft_delete_object()), or there is no object lock 74 * yet (by soft_build_XXX_object() during creating an object). 75 */ 76 void 77 soft_cleanup_object(soft_object_t *objp) 78 { 79 /* 80 * Free the storage allocated to big integer attributes. 81 */ 82 soft_cleanup_object_bigint_attrs(objp); 83 84 /* 85 * Free the storage allocated to the extra attribute list. 86 */ 87 soft_cleanup_extra_attr(objp); 88 89 /* 90 * Free the storage allocated to certificate attributes. 91 */ 92 soft_cleanup_cert_object(objp); 93 } 94 95 96 /* 97 * Create a new object. Copy the attributes that can be modified 98 * (in the boolean attribute mask field and extra attribute list) 99 * from the old object to the new object. 100 * 101 * The caller of this function holds the lock on the old object. 102 */ 103 CK_RV 104 soft_copy_object(soft_object_t *old_object, soft_object_t **new_object, 105 CK_ULONG object_func, soft_session_t *sp) 106 { 107 108 CK_RV rv = CKR_OK; 109 soft_object_t *new_objp = NULL; 110 CK_ATTRIBUTE_INFO_PTR attrp; 111 112 /* Allocate new object. */ 113 new_objp = calloc(1, sizeof (soft_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 new_objp->cert_type = old_object->cert_type; 120 new_objp->object_type = old_object->object_type; 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 = soft_copy_extra_attr(attrp, new_objp); 131 if (rv != CKR_OK) { 132 soft_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 (object_func == SOFT_SET_ATTR_VALUE) { 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 155 switch (object_func) { 156 case SOFT_COPY_OBJ_ORIG_SH: 157 new_objp->session_handle = old_object->session_handle; 158 break; 159 case SOFT_COPY_OBJECT: 160 /* 161 * Save the session handle of the C_CopyObject function 162 * in the new copy of the session object. 163 */ 164 new_objp->session_handle = sp->handle; 165 break; 166 } 167 168 (void) pthread_cond_init(&(new_objp->obj_free_cond), NULL); 169 (void) pthread_mutex_init(&(new_objp->object_mutex), NULL); 170 /* copy key related information */ 171 switch (new_objp->class) { 172 case CKO_PUBLIC_KEY: 173 rv = soft_copy_public_key_attr(OBJ_PUB(old_object), 174 &(OBJ_PUB(new_objp)), new_objp->key_type); 175 break; 176 case CKO_PRIVATE_KEY: 177 rv = soft_copy_private_key_attr(OBJ_PRI(old_object), 178 &(OBJ_PRI(new_objp)), new_objp->key_type); 179 break; 180 case CKO_SECRET_KEY: 181 rv = soft_copy_secret_key_attr(OBJ_SEC(old_object), 182 &(OBJ_SEC(new_objp))); 183 break; 184 case CKO_DOMAIN_PARAMETERS: 185 rv = soft_copy_domain_attr(OBJ_DOM(old_object), 186 &(OBJ_DOM(new_objp)), new_objp->key_type); 187 break; 188 case CKO_CERTIFICATE: 189 rv = soft_copy_certificate(OBJ_CERT(old_object), 190 &(OBJ_CERT(new_objp)), new_objp->cert_type); 191 break; 192 default: 193 /* should never be this case */ 194 break; 195 } 196 if (rv != CKR_OK) { 197 /* 198 * don't need to cleanup the memory from failure of copying 199 * any key related stuff. Each individual function for 200 * copying key attr will free the memory if it fails 201 */ 202 soft_cleanup_extra_attr(new_objp); 203 free(new_objp); 204 } 205 return (rv); 206 } 207 208 209 /* 210 * Copy the attributes (in the boolean attribute mask field and 211 * extra attribute list) from the new object back to the original 212 * object. Also, clean up and release all the storage in the extra 213 * attribute list of the original object. 214 * 215 * The caller of this function holds the lock on the old object. 216 */ 217 void 218 soft_merge_object(soft_object_t *old_object, soft_object_t *new_object) 219 { 220 old_object->bool_attr_mask = new_object->bool_attr_mask; 221 soft_cleanup_extra_attr(old_object); 222 old_object->extra_attrlistp = new_object->extra_attrlistp; 223 } 224 225 /* 226 * Sets *object_p to the soft_object_t corresponding to hObject. If 227 * hObject is valid, and not in the deleting state, CKR_OK is returned, 228 * otherwise an error is returned. If hObject is valid and refhold is B_TRUE, 229 * the object is also held. 230 */ 231 CK_RV 232 handle2object(CK_OBJECT_HANDLE hObject, soft_object_t **object_p, 233 boolean_t refhold) 234 { 235 soft_object_t *obj; 236 soft_object_t node; 237 238 (void) memset(&node, 0, sizeof (node)); 239 node.handle = hObject; 240 241 VERIFY0(pthread_mutex_lock(&soft_object_mutex)); 242 if ((obj = avl_find(&soft_object_tree, &node, NULL)) == NULL || 243 obj->magic_marker != SOFTTOKEN_OBJECT_MAGIC) { 244 VERIFY0(pthread_mutex_unlock(&soft_object_mutex)); 245 return (CKR_OBJECT_HANDLE_INVALID); 246 } 247 248 (void) pthread_mutex_lock(&obj->object_mutex); 249 VERIFY0(pthread_mutex_unlock(&soft_object_mutex)); 250 251 if (obj->obj_delete_sync & OBJECT_IS_DELETING) { 252 (void) pthread_mutex_unlock(&obj->object_mutex); 253 return (CKR_OBJECT_HANDLE_INVALID); 254 } 255 256 if (refhold) 257 obj->obj_refcnt++; 258 259 (void) pthread_mutex_unlock(&obj->object_mutex); 260 261 *object_p = obj; 262 return (CKR_OK); 263 } 264 265 CK_ULONG 266 set_objecthandle(soft_object_t *obj) 267 { 268 avl_index_t where; 269 270 (void) pthread_mutex_lock(&soft_object_mutex); 271 272 do { 273 arc4random_buf(&obj->handle, sizeof (obj->handle)); 274 if (obj->handle == CK_INVALID_HANDLE) 275 continue; 276 } while (avl_find(&soft_object_tree, obj, &where) != NULL); 277 278 avl_insert(&soft_object_tree, obj, where); 279 280 (void) pthread_mutex_unlock(&soft_object_mutex); 281 282 return (obj->handle); 283 } 284 285 /* 286 * Create a new object struct, and add it to the session's object list. 287 */ 288 CK_RV 289 soft_add_object(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, 290 CK_OBJECT_HANDLE_PTR objecthandle_p, soft_session_t *sp) 291 { 292 293 CK_RV rv = CKR_OK; 294 soft_object_t *new_objp = NULL; 295 296 new_objp = calloc(1, sizeof (soft_object_t)); 297 if (new_objp == NULL) { 298 return (CKR_HOST_MEMORY); 299 } 300 301 new_objp->extra_attrlistp = NULL; 302 303 /* 304 * Validate attribute template and fill in the attributes 305 * in the soft_object_t. 306 */ 307 rv = soft_build_object(pTemplate, ulCount, new_objp); 308 if (rv != CKR_OK) { 309 goto fail_cleanup1; 310 } 311 312 rv = soft_pin_expired_check(new_objp); 313 if (rv != CKR_OK) { 314 goto fail_cleanup2; 315 } 316 317 rv = soft_object_write_access_check(sp, new_objp); 318 if (rv != CKR_OK) { 319 goto fail_cleanup2; 320 } 321 322 /* Initialize the rest of stuffs in soft_object_t. */ 323 (void) pthread_cond_init(&new_objp->obj_free_cond, NULL); 324 (void) pthread_mutex_init(&new_objp->object_mutex, NULL); 325 new_objp->magic_marker = SOFTTOKEN_OBJECT_MAGIC; 326 new_objp->obj_refcnt = 0; 327 new_objp->obj_delete_sync = 0; 328 329 /* Write the new token object to the keystore */ 330 if (IS_TOKEN_OBJECT(new_objp)) { 331 if (!soft_keystore_status(KEYSTORE_INITIALIZED)) { 332 rv = CKR_DEVICE_REMOVED; 333 goto fail_cleanup2; 334 } 335 new_objp->version = 1; 336 rv = soft_put_object_to_keystore(new_objp); 337 if (rv != CKR_OK) { 338 (void) pthread_cond_destroy(&new_objp->obj_free_cond); 339 (void) pthread_mutex_destroy(&new_objp->object_mutex); 340 goto fail_cleanup2; 341 } 342 new_objp->session_handle = CK_INVALID_HANDLE; 343 soft_add_token_object_to_slot(new_objp); 344 345 *objecthandle_p = set_objecthandle(new_objp); 346 347 return (CKR_OK); 348 } 349 350 new_objp->session_handle = sp->handle; 351 352 /* Add the new object to the session's object list. */ 353 soft_add_object_to_session(new_objp, sp); 354 355 *objecthandle_p = set_objecthandle(new_objp); 356 357 return (CKR_OK); 358 359 fail_cleanup2: 360 /* 361 * When any error occurs after soft_build_object(), we will need to 362 * clean up the memory allocated by the soft_build_object(). 363 */ 364 soft_cleanup_object(new_objp); 365 366 fail_cleanup1: 367 if (new_objp) { 368 /* 369 * The storage allocated inside of this object should have 370 * been cleaned up by the soft_build_object() if it failed. 371 * Therefore, we can safely free the object. 372 */ 373 free(new_objp); 374 } 375 376 return (rv); 377 378 } 379 380 381 /* 382 * Remove an object from the session's object list. 383 * 384 * The caller of this function holds the session lock. 385 */ 386 CK_RV 387 soft_remove_object_from_session(soft_object_t *objp, soft_session_t *sp) 388 { 389 soft_object_t *tmp_objp; 390 boolean_t found = B_FALSE; 391 392 /* 393 * Remove the object from the session's object list. 394 */ 395 if ((sp == NULL) || 396 (sp->magic_marker != SOFTTOKEN_SESSION_MAGIC)) { 397 return (CKR_SESSION_HANDLE_INVALID); 398 } 399 400 if ((sp->object_list == NULL) || (objp == NULL) || 401 (objp->magic_marker != SOFTTOKEN_OBJECT_MAGIC)) { 402 return (CKR_OBJECT_HANDLE_INVALID); 403 } 404 405 tmp_objp = sp->object_list; 406 while (tmp_objp) { 407 if (tmp_objp == objp) { 408 found = B_TRUE; 409 break; 410 } 411 tmp_objp = tmp_objp->next; 412 } 413 if (!found) 414 return (CKR_OBJECT_HANDLE_INVALID); 415 416 if (sp->object_list == objp) { 417 /* Object is the first one in the list. */ 418 if (objp->next) { 419 sp->object_list = objp->next; 420 objp->next->prev = NULL; 421 } else { 422 /* Object is the only one in the list. */ 423 sp->object_list = NULL; 424 } 425 } else { 426 /* Object is not the first one in the list. */ 427 if (objp->next) { 428 /* Object is in the middle of the list. */ 429 objp->prev->next = objp->next; 430 objp->next->prev = objp->prev; 431 } else { 432 /* Object is the last one in the list. */ 433 objp->prev->next = NULL; 434 } 435 } 436 return (CKR_OK); 437 } 438 439 /* 440 * This function adds the to-be-freed session object to a linked list. 441 * When the number of objects queued in the linked list reaches the 442 * maximum threshold MAX_OBJ_TO_BE_FREED, it will free the first 443 * object (FIFO) in the list. 444 */ 445 void 446 object_delay_free(soft_object_t *objp) 447 { 448 soft_object_t *tmp; 449 450 (void) pthread_mutex_lock(&obj_delay_freed.obj_to_be_free_mutex); 451 452 /* Add the newly deleted object at the end of the list */ 453 objp->next = NULL; 454 if (obj_delay_freed.first == NULL) { 455 obj_delay_freed.last = objp; 456 obj_delay_freed.first = objp; 457 } else { 458 obj_delay_freed.last->next = objp; 459 obj_delay_freed.last = objp; 460 } 461 462 if (++obj_delay_freed.count >= MAX_OBJ_TO_BE_FREED) { 463 /* 464 * Free the first object in the list only if 465 * the total count reaches maximum threshold. 466 */ 467 obj_delay_freed.count--; 468 tmp = obj_delay_freed.first->next; 469 free(obj_delay_freed.first); 470 obj_delay_freed.first = tmp; 471 } 472 (void) pthread_mutex_unlock(&obj_delay_freed.obj_to_be_free_mutex); 473 } 474 475 static void 476 soft_delete_object_cleanup(soft_object_t *objp, boolean_t force) 477 { 478 /* Acquire the lock on the object. */ 479 (void) pthread_mutex_lock(&objp->object_mutex); 480 481 /* 482 * Make sure another thread hasn't freed the object. 483 */ 484 if (objp->magic_marker != SOFTTOKEN_OBJECT_MAGIC) { 485 (void) pthread_mutex_unlock(&objp->object_mutex); 486 return; 487 } 488 489 /* 490 * The deletion of an object must be blocked when the object 491 * reference count is not zero. This means if any object related 492 * operation starts prior to the delete object operation gets in, 493 * the object deleting thread must wait for the non-deleting 494 * operation to be completed before it can proceed the delete 495 * operation. 496 * 497 * Unless we are being forced to shut everything down, this only 498 * happens if the libraries _fini() is running not of someone 499 * explicitly called C_Finalize(). 500 */ 501 if (force) 502 objp->obj_refcnt = 0; 503 504 while (objp->obj_refcnt != 0) { 505 /* 506 * We set the OBJECT_REFCNT_WAITING flag before we put 507 * this deleting thread in a wait state, so other non-deleting 508 * operation thread will signal to wake it up only when 509 * the object reference count becomes zero and this flag 510 * is set. 511 */ 512 objp->obj_delete_sync |= OBJECT_REFCNT_WAITING; 513 (void) pthread_cond_wait(&objp->obj_free_cond, 514 &objp->object_mutex); 515 } 516 517 objp->obj_delete_sync &= ~OBJECT_REFCNT_WAITING; 518 519 /* Mark object as no longer valid. */ 520 objp->magic_marker = 0; 521 522 (void) pthread_cond_destroy(&objp->obj_free_cond); 523 524 /* 525 * Cleanup the contents of this object such as free all the 526 * storage allocated for this object. 527 */ 528 soft_cleanup_object(objp); 529 530 (void) pthread_mutex_lock(&soft_object_mutex); 531 avl_remove(&soft_object_tree, objp); 532 (void) pthread_mutex_unlock(&soft_object_mutex); 533 534 /* Reset OBJECT_IS_DELETING flag. */ 535 objp->obj_delete_sync &= ~OBJECT_IS_DELETING; 536 537 (void) pthread_mutex_unlock(&objp->object_mutex); 538 /* Destroy the object lock */ 539 (void) pthread_mutex_destroy(&objp->object_mutex); 540 541 /* Free the object itself */ 542 if (IS_TOKEN_OBJECT(objp)) 543 free(objp); 544 else 545 /* 546 * Delay freeing the session object as S1WS/NSS uses session 547 * objects for its SSL Handshake. 548 */ 549 (void) object_delay_free(objp); 550 } 551 552 /* 553 * Delete an object: 554 * - Remove the object from the session's object list. 555 * Holding the lock on the session which the object was created at 556 * is needed to do this. 557 * - Release the storage allocated to the object. 558 * 559 * The boolean argument lock_held is used to indicate that whether 560 * the caller holds the session lock or not. 561 * - When called by soft_delete_all_objects_in_session() -- the 562 * lock_held = TRUE. 563 * 564 * When the caller does not hold the session lock, this function 565 * will acquire that lock in order to proceed, and also release 566 * that lock before returning to caller. 567 */ 568 void 569 soft_delete_object(soft_session_t *sp, soft_object_t *objp, 570 boolean_t force, boolean_t lock_held) 571 { 572 573 /* 574 * Check to see if the caller holds the lock on the session. 575 * If not, we need to acquire that lock in order to proceed. 576 */ 577 if (!lock_held) { 578 /* Acquire the session lock. */ 579 (void) pthread_mutex_lock(&sp->session_mutex); 580 } 581 582 /* Remove the object from the session's object list first. */ 583 if (soft_remove_object_from_session(objp, sp) != CKR_OK) { 584 if (!lock_held) { 585 (void) pthread_mutex_unlock(&sp->session_mutex); 586 } 587 return; 588 } 589 590 if (!lock_held) { 591 /* 592 * If the session lock is obtained by this function, 593 * then release that lock after removing the object 594 * from session's object list. 595 * We want the releasing of the object storage to 596 * be done without holding the session lock. 597 */ 598 (void) pthread_mutex_unlock(&sp->session_mutex); 599 } 600 601 soft_delete_object_cleanup(objp, force); 602 } 603 604 605 /* 606 * Delete all the objects in a session. The caller holds the lock 607 * on the session. 608 */ 609 void 610 soft_delete_all_objects_in_session(soft_session_t *sp, boolean_t force) 611 { 612 soft_object_t *objp = sp->object_list; 613 soft_object_t *objp1; 614 615 /* Delete all the objects in the session. */ 616 while (objp) { 617 objp1 = objp->next; 618 619 /* 620 * Delete an object by calling soft_delete_object() 621 * with a TRUE boolean argument indicating that 622 * the caller holds the lock on the session. 623 */ 624 soft_delete_object(sp, objp, force, B_TRUE); 625 626 objp = objp1; 627 } 628 } 629 630 static CK_RV 631 add_to_search_result(soft_object_t *obj, find_context_t *fcontext, 632 CK_ULONG *num_result_alloc) 633 { 634 /* 635 * allocate space for storing results if the currently 636 * allocated space is not enough 637 */ 638 if (*num_result_alloc <= fcontext->num_results) { 639 fcontext->objs_found = realloc(fcontext->objs_found, 640 sizeof (soft_object_t *) * (*num_result_alloc + BUFSIZ)); 641 if (fcontext->objs_found == NULL) { 642 return (CKR_HOST_MEMORY); 643 } 644 *num_result_alloc += BUFSIZ; 645 } 646 647 (fcontext->objs_found)[(fcontext->num_results)++] = obj; 648 return (CKR_OK); 649 } 650 651 static CK_RV 652 search_for_objects(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, 653 find_context_t *fcontext) 654 { 655 soft_session_t *session_p; 656 soft_object_t *obj; 657 CK_OBJECT_CLASS pclasses[6]; /* classes attrs possibly exist */ 658 CK_ULONG num_pclasses; /* number of possible classes */ 659 CK_ULONG num_result_alloc = 0; /* spaces allocated for results */ 660 CK_RV rv = CKR_OK; 661 /* whether CKA_TOKEN flag specified or not */ 662 boolean_t token_specified = B_FALSE; 663 /* value of CKA_TOKEN flag, if specified */ 664 boolean_t token_flag_val = B_FALSE; 665 CK_ULONG i; 666 667 if (ulCount > 0) { 668 /* there are some search requirement */ 669 soft_process_find_attr(pclasses, &num_pclasses, 670 pTemplate, ulCount); 671 } 672 673 for (i = 0; i < ulCount; i++) { 674 if (pTemplate[i].type == CKA_PRIVATE) { 675 (void) pthread_mutex_lock(&soft_giant_mutex); 676 if (soft_slot.userpin_change_needed) { 677 (void) pthread_mutex_unlock(&soft_giant_mutex); 678 return (CKR_PIN_EXPIRED); 679 } 680 (void) pthread_mutex_unlock(&soft_giant_mutex); 681 } 682 } 683 684 /* 685 * look through template and see if it explicitly specifies 686 * whether we need to look for token objects or not 687 */ 688 for (i = 0; i < ulCount; i++) { 689 if (pTemplate[i].type == CKA_TOKEN) { 690 token_specified = B_TRUE; 691 token_flag_val = *((CK_BBOOL *)pTemplate[i].pValue); 692 break; 693 } 694 } 695 696 /* 697 * Need go through token objects if it explicitly say so, or 698 * it is not mentioned in the template. And this will ONLY be 699 * done when the keystore exists. Otherwise, we will skip re-loading 700 * the token objects. 701 * 702 * If a session has not logged into the token, only public 703 * objects, if any, will be searched. If a session is logged 704 * into the token, all public and private objects in the keystore 705 * are searched. 706 */ 707 if (((token_flag_val) || (!token_specified)) && 708 soft_keystore_status(KEYSTORE_INITIALIZED)) { 709 /* acquire token session lock */ 710 (void) pthread_mutex_lock(&soft_slot.slot_mutex); 711 rv = refresh_token_objects(); 712 if (rv != CKR_OK) { 713 (void) pthread_mutex_unlock(&soft_slot.slot_mutex); 714 return (rv); 715 } 716 obj = soft_slot.token_object_list; 717 while (obj) { 718 (void) pthread_mutex_lock(&obj->object_mutex); 719 if (((token_specified) && (ulCount > 1)) || 720 ((!token_specified) && (ulCount > 0))) { 721 if (soft_find_match_attrs(obj, pclasses, 722 num_pclasses, pTemplate, ulCount)) { 723 rv = add_to_search_result( 724 obj, fcontext, &num_result_alloc); 725 } 726 } else { 727 /* no search criteria, just record the object */ 728 rv = add_to_search_result(obj, fcontext, 729 &num_result_alloc); 730 } 731 (void) pthread_mutex_unlock(&obj->object_mutex); 732 if (rv != CKR_OK) { 733 (void) pthread_mutex_unlock 734 (&soft_slot.slot_mutex); 735 return (rv); 736 } 737 obj = obj->next; 738 } 739 (void) pthread_mutex_unlock(&soft_slot.slot_mutex); 740 } 741 742 if (token_flag_val) { 743 /* no need to look through session objects */ 744 return (rv); 745 } 746 747 /* Acquire the global session list lock */ 748 (void) pthread_mutex_lock(&soft_sessionlist_mutex); 749 750 /* 751 * Go through all objects in each session. 752 * Acquire individual session lock for the session 753 * we are searching. 754 */ 755 session_p = soft_session_list; 756 while (session_p) { 757 (void) pthread_mutex_lock(&session_p->session_mutex); 758 759 obj = session_p->object_list; 760 while (obj) { 761 (void) pthread_mutex_lock(&obj->object_mutex); 762 if (ulCount > 0) { 763 if (soft_find_match_attrs(obj, pclasses, 764 num_pclasses, pTemplate, ulCount)) { 765 rv = add_to_search_result( 766 obj, fcontext, &num_result_alloc); 767 } 768 } else { 769 /* no search criteria, just record the object */ 770 rv = add_to_search_result(obj, fcontext, 771 &num_result_alloc); 772 } 773 (void) pthread_mutex_unlock(&obj->object_mutex); 774 if (rv != CKR_OK) { 775 (void) pthread_mutex_unlock( 776 &session_p->session_mutex); 777 goto cleanup; 778 } 779 obj = obj->next; 780 } 781 (void) pthread_mutex_unlock(&session_p->session_mutex); 782 session_p = session_p->next; 783 } 784 785 cleanup: 786 /* Release the global session list lock */ 787 (void) pthread_mutex_unlock(&soft_sessionlist_mutex); 788 return (rv); 789 } 790 791 /* 792 * Initialize the context for C_FindObjects() calls 793 */ 794 CK_RV 795 soft_find_objects_init(soft_session_t *sp, CK_ATTRIBUTE_PTR pTemplate, 796 CK_ULONG ulCount) 797 { 798 799 CK_RV rv = CKR_OK; 800 CK_OBJECT_CLASS class; /* for soft_validate_attr(). Value unused */ 801 find_context_t *fcontext; 802 803 if (ulCount) { 804 rv = soft_validate_attr(pTemplate, ulCount, &class); 805 /* Make sure all attributes in template are valid */ 806 if (rv != CKR_OK) { 807 return (rv); 808 } 809 } 810 811 812 /* prepare the find context */ 813 fcontext = calloc(1, sizeof (find_context_t)); 814 if (fcontext == NULL) { 815 return (CKR_HOST_MEMORY); 816 } 817 818 rv = search_for_objects(pTemplate, ulCount, fcontext); 819 if (rv != CKR_OK) { 820 free(fcontext); 821 return (rv); 822 } 823 824 /* store the find_context in the session */ 825 sp->find_objects.context = (CK_VOID_PTR)fcontext; 826 827 return (rv); 828 } 829 830 void 831 soft_find_objects_final(soft_session_t *sp) 832 { 833 find_context_t *fcontext; 834 835 fcontext = sp->find_objects.context; 836 sp->find_objects.context = NULL; 837 sp->find_objects.flags = 0; 838 if (fcontext->objs_found != NULL) { 839 free(fcontext->objs_found); 840 } 841 842 free(fcontext); 843 } 844 845 void 846 soft_find_objects(soft_session_t *sp, CK_OBJECT_HANDLE *obj_found, 847 CK_ULONG max_obj_requested, CK_ULONG *found_obj_count) 848 { 849 find_context_t *fcontext; 850 CK_ULONG num_obj_found = 0; 851 CK_ULONG i; 852 soft_object_t *obj; 853 854 fcontext = sp->find_objects.context; 855 856 for (i = fcontext->next_result_index; 857 ((num_obj_found < max_obj_requested) && 858 (i < fcontext->num_results)); 859 i++) { 860 obj = fcontext->objs_found[i]; 861 if (obj != NULL) { 862 (void) pthread_mutex_lock(&obj->object_mutex); 863 /* a sanity check to make sure the obj is still valid */ 864 if (obj->magic_marker == SOFTTOKEN_OBJECT_MAGIC) { 865 obj_found[num_obj_found] = obj->handle; 866 num_obj_found++; 867 } 868 (void) pthread_mutex_unlock(&obj->object_mutex); 869 } 870 } 871 fcontext->next_result_index = i; 872 *found_obj_count = num_obj_found; 873 } 874 875 /* 876 * Below are the token object related functions 877 */ 878 void 879 soft_add_token_object_to_slot(soft_object_t *objp) 880 { 881 882 (void) pthread_mutex_lock(&soft_slot.slot_mutex); 883 884 /* Insert the new object in front of slot's token object list. */ 885 if (soft_slot.token_object_list == NULL) { 886 soft_slot.token_object_list = objp; 887 objp->next = NULL; 888 objp->prev = NULL; 889 } else { 890 soft_slot.token_object_list->prev = objp; 891 objp->next = soft_slot.token_object_list; 892 objp->prev = NULL; 893 soft_slot.token_object_list = objp; 894 } 895 896 (void) pthread_mutex_unlock(&soft_slot.slot_mutex); 897 898 } 899 900 void 901 soft_remove_token_object_from_slot(soft_object_t *objp, boolean_t lock_held) 902 { 903 904 if (!lock_held) 905 (void) pthread_mutex_lock(&soft_slot.slot_mutex); 906 907 /* 908 * Remove the object from the slot's token object list. 909 */ 910 if (soft_slot.token_object_list == objp) { 911 /* Object is the first one in the list. */ 912 if (objp->next) { 913 soft_slot.token_object_list = objp->next; 914 objp->next->prev = NULL; 915 } else { 916 /* Object is the only one in the list. */ 917 soft_slot.token_object_list = NULL; 918 } 919 } else { 920 /* Object is not the first one in the list. */ 921 if (objp->next) { 922 /* Object is in the middle of the list. */ 923 objp->prev->next = objp->next; 924 objp->next->prev = objp->prev; 925 } else { 926 /* Object is the last one in the list. */ 927 objp->prev->next = NULL; 928 } 929 } 930 931 if (!lock_held) 932 (void) pthread_mutex_unlock(&soft_slot.slot_mutex); 933 } 934 935 void 936 soft_delete_token_object(soft_object_t *objp, boolean_t persistent, 937 boolean_t lock_held) 938 { 939 940 if (!lock_held) 941 (void) pthread_mutex_lock(&soft_slot.slot_mutex); 942 if (persistent) 943 /* Delete the object from the keystore. */ 944 (void) soft_keystore_del_obj(&objp->ks_handle, B_FALSE); 945 946 /* Remove the object from the slot's token object list. */ 947 soft_remove_token_object_from_slot(objp, B_TRUE); 948 if (!lock_held) 949 (void) pthread_mutex_unlock(&soft_slot.slot_mutex); 950 951 soft_delete_object_cleanup(objp, B_FALSE); 952 } 953 954 void 955 soft_delete_all_in_core_token_objects(token_obj_type_t type) 956 { 957 958 soft_object_t *objp; 959 soft_object_t *objp1; 960 961 (void) pthread_mutex_lock(&soft_slot.slot_mutex); 962 objp = soft_slot.token_object_list; 963 964 switch (type) { 965 case PRIVATE_TOKEN: 966 while (objp) { 967 objp1 = objp->next; 968 if (objp->object_type == TOKEN_PRIVATE) { 969 soft_delete_token_object(objp, B_FALSE, B_TRUE); 970 } 971 objp = objp1; 972 } 973 break; 974 975 case PUBLIC_TOKEN: 976 while (objp) { 977 objp1 = objp->next; 978 if (objp->object_type == TOKEN_PUBLIC) { 979 soft_delete_token_object(objp, B_FALSE, B_TRUE); 980 } 981 objp = objp1; 982 } 983 break; 984 985 case ALL_TOKEN: 986 while (objp) { 987 objp1 = objp->next; 988 soft_delete_token_object(objp, B_FALSE, B_TRUE); 989 objp = objp1; 990 } 991 break; 992 } 993 994 (void) pthread_mutex_unlock(&soft_slot.slot_mutex); 995 996 } 997 998 /* 999 * Mark all the token objects in the global list to be valid. 1000 */ 1001 void 1002 soft_validate_token_objects(boolean_t validate) 1003 { 1004 1005 soft_object_t *objp; 1006 1007 (void) pthread_mutex_lock(&soft_slot.slot_mutex); 1008 1009 objp = soft_slot.token_object_list; 1010 1011 while (objp) { 1012 if (validate) 1013 objp->magic_marker = SOFTTOKEN_OBJECT_MAGIC; 1014 else 1015 objp->magic_marker = 0; 1016 1017 objp = objp->next; 1018 } 1019 1020 (void) pthread_mutex_unlock(&soft_slot.slot_mutex); 1021 1022 } 1023 1024 /* 1025 * Verify user's write access rule to the token object. 1026 */ 1027 CK_RV 1028 soft_object_write_access_check(soft_session_t *sp, soft_object_t *objp) 1029 { 1030 1031 /* 1032 * This function is called by C_CreateObject, C_CopyObject, 1033 * C_DestroyObject, C_SetAttributeValue, C_GenerateKey, 1034 * C_GenerateKeyPairs, C_DeriveKey. All of them will write 1035 * the token object to the keystore. 1036 */ 1037 (void) pthread_mutex_lock(&soft_giant_mutex); 1038 if (!soft_slot.authenticated) { 1039 (void) pthread_mutex_unlock(&soft_giant_mutex); 1040 /* User is not logged in */ 1041 if (sp->flags & CKF_RW_SESSION) { 1042 /* 1043 * For R/W Public Session: 1044 * we allow write access to public session or token 1045 * object, but not for private token/session object. 1046 */ 1047 if ((objp->object_type == TOKEN_PRIVATE) || 1048 (objp->object_type == SESSION_PRIVATE)) { 1049 return (CKR_USER_NOT_LOGGED_IN); 1050 } 1051 } else { 1052 /* 1053 * For R/O Public Session: 1054 * we allow write access to public session object. 1055 */ 1056 if (objp->object_type != SESSION_PUBLIC) 1057 return (CKR_SESSION_READ_ONLY); 1058 } 1059 } else { 1060 (void) pthread_mutex_unlock(&soft_giant_mutex); 1061 /* User is logged in */ 1062 if (!(sp->flags & CKF_RW_SESSION)) { 1063 /* 1064 * For R/O User Function Session: 1065 * we allow write access to public or private 1066 * session object, but not for public or private 1067 * token object. 1068 */ 1069 if ((objp->object_type == TOKEN_PUBLIC) || 1070 (objp->object_type == TOKEN_PRIVATE)) { 1071 return (CKR_SESSION_READ_ONLY); 1072 } 1073 } 1074 } 1075 1076 return (CKR_OK); 1077 } 1078 1079 /* 1080 * Verify if user is required to setpin when accessing the 1081 * private token/session object. 1082 */ 1083 CK_RV 1084 soft_pin_expired_check(soft_object_t *objp) 1085 { 1086 1087 /* 1088 * This function is called by C_CreateObject, C_CopyObject, 1089 * C_DestroyObject, C_GenerateKey, 1090 * C_GenerateKeyPairs, C_DeriveKey. 1091 * All of them will return CKR_PIN_EXPIRED if the 1092 * "userpin_change_needed" is set. 1093 * 1094 * The following functions will not be necessary to call 1095 * this routine even though CKR_PIN_EXPIRED is one of the 1096 * valid error code they might return. These functions are: 1097 * C_EncryptInit, C_DecryptInit, C_DigestInit, C_SignInit, 1098 * C_SignRecoverInit, C_VerifyInit, C_VerifyRecoverInit. 1099 * This is because they will not get the object handle 1100 * before the above functions are called. 1101 */ 1102 1103 (void) pthread_mutex_lock(&soft_giant_mutex); 1104 if (soft_slot.userpin_change_needed) { 1105 /* 1106 * Access private token/session object but user's 1107 * PIN is expired or never set. 1108 */ 1109 if ((objp->object_type == TOKEN_PRIVATE) || 1110 (objp->object_type == SESSION_PRIVATE)) { 1111 (void) pthread_mutex_unlock(&soft_giant_mutex); 1112 return (CKR_PIN_EXPIRED); 1113 } 1114 } 1115 1116 (void) pthread_mutex_unlock(&soft_giant_mutex); 1117 return (CKR_OK); 1118 } 1119 1120 /* 1121 * Copy the selected fields from new token object to old 1122 * token object. 1123 */ 1124 CK_RV 1125 soft_copy_to_old_object(soft_object_t *new, soft_object_t *old) 1126 { 1127 1128 CK_RV rv = CKR_OK; 1129 CK_ATTRIBUTE_INFO_PTR attrp; 1130 1131 old->class = new->class; 1132 old->bool_attr_mask = new->bool_attr_mask; 1133 soft_cleanup_extra_attr(old); 1134 attrp = new->extra_attrlistp; 1135 while (attrp) { 1136 rv = soft_copy_extra_attr(attrp, old); 1137 if (rv != CKR_OK) { 1138 soft_cleanup_extra_attr(old); 1139 return (rv); 1140 } 1141 attrp = attrp->next; 1142 } 1143 1144 /* Done with copying all information that can be modified */ 1145 return (CKR_OK); 1146 } 1147 1148 /* 1149 * Update an existing object with new data from keystore. 1150 */ 1151 CK_RV 1152 soft_update_object(ks_obj_t *ks_obj, soft_object_t *old_obj) 1153 { 1154 1155 soft_object_t *new_object; 1156 CK_RV rv; 1157 1158 new_object = calloc(1, sizeof (soft_object_t)); 1159 if (new_object == NULL) 1160 return (CKR_HOST_MEMORY); 1161 1162 rv = soft_keystore_unpack_obj(new_object, ks_obj); 1163 if (rv != CKR_OK) { 1164 soft_cleanup_object(new_object); 1165 free(new_object); 1166 return (rv); 1167 } 1168 rv = soft_copy_to_old_object(new_object, old_obj); 1169 1170 soft_cleanup_object(new_object); 1171 free(new_object); 1172 return (CKR_OK); 1173 } 1174 1175 1176 CK_RV 1177 soft_keystore_load_latest_object(soft_object_t *old_obj) 1178 { 1179 1180 uint_t version; 1181 ks_obj_t *ks_obj = NULL; 1182 CK_RV rv = CKR_OK; 1183 1184 /* 1185 * Get the current version number from the keystore for 1186 * the specified token object. 1187 */ 1188 if (soft_keystore_get_object_version(&old_obj->ks_handle, &version, 1189 B_FALSE) == 1) 1190 return (CKR_FUNCTION_FAILED); 1191 1192 /* 1193 * If the keystore version is newer than the in-core version, 1194 * re-read the token object from the keystore. 1195 */ 1196 if (old_obj->version != version) { 1197 rv = soft_keystore_get_single_obj(&old_obj->ks_handle, 1198 &ks_obj, B_FALSE); 1199 if (rv != CKR_OK) 1200 return (rv); 1201 old_obj->version = version; 1202 1203 /* 1204 * Update an existing object with new data from keystore. 1205 */ 1206 rv = soft_update_object(ks_obj, old_obj); 1207 free(ks_obj->buf); 1208 free(ks_obj); 1209 } 1210 1211 return (rv); 1212 } 1213 1214 /* 1215 * Insert an object into a list of soft_object_t objects. It is assumed 1216 * that the object to be inserted doesn't previously belong to any list 1217 */ 1218 static void 1219 insert_into_list(soft_object_t **list, soft_object_t **end_of_list, 1220 soft_object_t *objp) 1221 { 1222 if (*list == NULL) { 1223 *list = objp; 1224 objp->next = NULL; 1225 objp->prev = NULL; 1226 *end_of_list = objp; 1227 } else { 1228 (*list)->prev = objp; 1229 objp->next = *list; 1230 objp->prev = NULL; 1231 *list = objp; 1232 } 1233 } 1234 1235 /* 1236 * Move an object from an existing list into a new list of 1237 * soft_object_t objects. 1238 */ 1239 static void 1240 move_into_list(soft_object_t **existing_list, soft_object_t **new_list, 1241 soft_object_t **end_of_list, soft_object_t *objp) 1242 { 1243 1244 /* first, remove object from existing list */ 1245 if (objp == *existing_list) { 1246 /* first item in list */ 1247 if (objp->next) { 1248 *existing_list = objp->next; 1249 objp->next->prev = NULL; 1250 } else { 1251 *existing_list = NULL; 1252 } 1253 } else { 1254 if (objp->next) { 1255 objp->prev->next = objp->next; 1256 objp->next->prev = objp->prev; 1257 } else { 1258 objp->prev->next = NULL; 1259 } 1260 } 1261 1262 /* then, add into new list */ 1263 insert_into_list(new_list, end_of_list, objp); 1264 } 1265 1266 /* 1267 * Insert "new_list" into "existing_list", new list will always be inserted 1268 * into the front of existing list 1269 */ 1270 static void 1271 insert_list_into_list(soft_object_t **existing_list, 1272 soft_object_t *new_list, soft_object_t *end_new_list) 1273 { 1274 1275 if (new_list == NULL) { 1276 return; 1277 } 1278 1279 if (*existing_list == NULL) { 1280 *existing_list = new_list; 1281 } else { 1282 (*existing_list)->prev = end_new_list; 1283 end_new_list->next = *existing_list; 1284 *existing_list = new_list; 1285 } 1286 } 1287 1288 static void 1289 delete_all_objs_in_list(soft_object_t *list) 1290 { 1291 soft_object_t *objp, *objp_next; 1292 1293 if (list == NULL) { 1294 return; 1295 } 1296 1297 objp = list; 1298 while (objp) { 1299 objp_next = objp->next; 1300 soft_delete_object_cleanup(objp, B_FALSE); 1301 objp = objp_next; 1302 } 1303 } 1304 1305 /* 1306 * Makes sure that the list of in-core token objects are up to date 1307 * with respect to the on disk keystore. Other process/applications 1308 * might have modified the keystore since the objects are last loaded 1309 * 1310 * If there's any error from refreshing the token object list (eg: unable 1311 * to read, unable to unpack and object...etc), the in-core list 1312 * will be restored back to the state before the refresh. An error 1313 * will be returned to indicate the failure. 1314 * 1315 * It is assumed that the caller holds the lock for the token slot 1316 */ 1317 CK_RV 1318 refresh_token_objects() 1319 { 1320 uint_t on_disk_ks_version; 1321 ks_obj_t *on_disk_list = NULL, *tmp_on_disk, *next_on_disk; 1322 soft_object_t *in_core_obj, *tmp_incore_obj, *new_objp = NULL; 1323 CK_RV rv = CKR_OK; 1324 1325 /* deleted in-core objects */ 1326 soft_object_t *del_objs_list = NULL; 1327 soft_object_t *end_del_objs_list = NULL; 1328 1329 /* modified in-core objects */ 1330 soft_object_t *mod_objs_list = NULL; 1331 soft_object_t *end_mod_objs_list = NULL; 1332 1333 /* 1334 * copy of modified in-core objects, in case we need 1335 * undo the change 1336 */ 1337 soft_object_t *copy_of_mod_objs_list = NULL; 1338 soft_object_t *end_copy_of_mod_objs_list = NULL; 1339 1340 /* objects to be added to the in-core list */ 1341 soft_object_t *added_objs_list = NULL; 1342 soft_object_t *end_added_objs_list = NULL; 1343 1344 if (soft_keystore_get_version(&on_disk_ks_version, B_FALSE) != 0) { 1345 return (CKR_FUNCTION_FAILED); 1346 } 1347 1348 (void) pthread_mutex_lock(&soft_giant_mutex); 1349 if (on_disk_ks_version == soft_slot.ks_version) { 1350 /* no change */ 1351 (void) pthread_mutex_unlock(&soft_giant_mutex); 1352 return (CKR_OK); 1353 } 1354 1355 if (soft_slot.authenticated) { 1356 /* get both public and private objects */ 1357 (void) pthread_mutex_unlock(&soft_giant_mutex); 1358 rv = soft_keystore_get_objs(ALL_TOKENOBJS, &on_disk_list, 1359 B_FALSE); 1360 } else { 1361 /* get both public objects only */ 1362 (void) pthread_mutex_unlock(&soft_giant_mutex); 1363 rv = soft_keystore_get_objs(PUB_TOKENOBJS, &on_disk_list, 1364 B_FALSE); 1365 } 1366 if (rv != CKR_OK) { 1367 return (rv); 1368 } 1369 1370 /* 1371 * The in-core tokens list will be updated as follows: 1372 * 1373 * Go through each item in the in-core tokens list. 1374 * Try to match the in-core object with one of the 1375 * objects from the on-disk list. If a match is made, 1376 * check the version number, and update in-core object 1377 * as necessary. 1378 * 1379 * If there's no match between in-core object with on-disk 1380 * object, that means the object is deleted since 1381 * last loaded. Will remove object from in-core list. 1382 * 1383 * When doing the matching of on-disk object list above, 1384 * Delete every matched on-disk object from the on-disk list 1385 * regardless the in-core object need to be deleted or not 1386 * 1387 * At the end of matching the in-core tokens list, if 1388 * any object is still left on the on-disk object list, 1389 * those are all new objects added since last load, 1390 * include all of them to the in-core list 1391 * 1392 * Since we need to be able to revert the in-core list 1393 * back to original state if there's any error with the refresh, 1394 * we need to do the following. 1395 * When an in-core object is "deleted", it is not immediately 1396 * deleted. It is moved to the list of "deleted_objects". 1397 * When an in-core object is "modified", a copy of the 1398 * unmodified object is made. After the object is modified, 1399 * it is temporarily moved to the "mod_objects" list 1400 * from the in-core list. 1401 * When the refresh is completed without any error, 1402 * the actual deleted objects and unmodified objects is deleted. 1403 */ 1404 in_core_obj = soft_slot.token_object_list; 1405 while (in_core_obj) { 1406 /* try to match object with on_disk_list */ 1407 ks_obj_t *ondisk_obj, *prev_ondisk_obj; 1408 boolean_t found = B_FALSE; 1409 soft_object_t *obj_copy; 1410 1411 ondisk_obj = on_disk_list; 1412 prev_ondisk_obj = NULL; 1413 1414 /* larval object that has not been written to disk */ 1415 if (in_core_obj->ks_handle.name[0] == '\0') { 1416 in_core_obj = in_core_obj->next; 1417 continue; 1418 } 1419 1420 while ((!found) && (ondisk_obj != NULL)) { 1421 1422 if (strcmp((char *)((ondisk_obj->ks_handle).name), 1423 (char *)((in_core_obj->ks_handle).name)) == 0) { 1424 1425 /* found a match */ 1426 found = B_TRUE; 1427 1428 /* update in-core obj if necessary */ 1429 if (ondisk_obj->obj_version != 1430 in_core_obj->version) { 1431 /* make a copy of before updating */ 1432 rv = soft_copy_object(in_core_obj, 1433 &obj_copy, SOFT_COPY_OBJ_ORIG_SH, 1434 NULL); 1435 if (rv != CKR_OK) { 1436 goto cleanup; 1437 } 1438 insert_into_list( 1439 ©_of_mod_objs_list, 1440 &end_copy_of_mod_objs_list, 1441 obj_copy); 1442 1443 rv = soft_update_object(ondisk_obj, 1444 in_core_obj); 1445 if (rv != CKR_OK) { 1446 goto cleanup; 1447 } 1448 move_into_list( 1449 &(soft_slot.token_object_list), 1450 &mod_objs_list, &end_mod_objs_list, 1451 in_core_obj); 1452 } 1453 1454 /* remove processed obj from on disk list */ 1455 if (ondisk_obj == on_disk_list) { 1456 /* first item */ 1457 on_disk_list = ondisk_obj->next; 1458 } else { 1459 prev_ondisk_obj->next = 1460 ondisk_obj->next; 1461 } 1462 free(ondisk_obj->buf); 1463 free(ondisk_obj); 1464 } else { 1465 prev_ondisk_obj = ondisk_obj; 1466 ondisk_obj = ondisk_obj->next; 1467 } 1468 } 1469 1470 if (!found) { 1471 tmp_incore_obj = in_core_obj->next; 1472 move_into_list(&(soft_slot.token_object_list), 1473 &del_objs_list, &end_del_objs_list, in_core_obj); 1474 in_core_obj = tmp_incore_obj; 1475 } else { 1476 in_core_obj = in_core_obj->next; 1477 } 1478 } 1479 1480 /* 1481 * At this point, if there's still anything on the on_disk_list, they 1482 * are all newly added objects since in-core list last loaded. 1483 * include all of them into the in-core list 1484 */ 1485 next_on_disk = on_disk_list; 1486 while (next_on_disk) { 1487 new_objp = calloc(1, sizeof (soft_object_t)); 1488 if (new_objp == NULL) { 1489 rv = CKR_HOST_MEMORY; 1490 goto cleanup; 1491 } 1492 1493 /* Convert the keystore format to memory format */ 1494 rv = soft_keystore_unpack_obj(new_objp, next_on_disk); 1495 if (rv != CKR_OK) { 1496 soft_cleanup_object(new_objp); 1497 free(new_objp); 1498 goto cleanup; 1499 } 1500 1501 insert_into_list(&added_objs_list, &end_added_objs_list, 1502 new_objp); 1503 1504 /* free the on_disk object */ 1505 tmp_on_disk = next_on_disk; 1506 next_on_disk = tmp_on_disk->next; 1507 free(tmp_on_disk->buf); 1508 free(tmp_on_disk); 1509 } 1510 1511 if (rv == CKR_OK) { 1512 (void) pthread_mutex_lock(&soft_giant_mutex); 1513 soft_slot.ks_version = on_disk_ks_version; 1514 (void) pthread_mutex_unlock(&soft_giant_mutex); 1515 1516 /* add the new objects into in-core list */ 1517 insert_list_into_list(&(soft_slot.token_object_list), 1518 added_objs_list, end_added_objs_list); 1519 1520 /* add modified objects back into the in-core list */ 1521 insert_list_into_list(&(soft_slot.token_object_list), 1522 mod_objs_list, end_mod_objs_list); 1523 1524 /* actually remove deleted objs, and copy of modified objs */ 1525 delete_all_objs_in_list(copy_of_mod_objs_list); 1526 delete_all_objs_in_list(del_objs_list); 1527 } 1528 1529 return (rv); 1530 1531 cleanup: 1532 next_on_disk = on_disk_list; 1533 while (next_on_disk) { 1534 tmp_on_disk = next_on_disk; 1535 next_on_disk = tmp_on_disk->next; 1536 free(tmp_on_disk->buf); 1537 free(tmp_on_disk); 1538 } 1539 1540 /* 1541 * restore the in-core list back to the original state by adding 1542 * copy of original objects and deleted objects back to list 1543 */ 1544 insert_list_into_list(&(soft_slot.token_object_list), 1545 del_objs_list, end_del_objs_list); 1546 insert_list_into_list(&(soft_slot.token_object_list), 1547 copy_of_mod_objs_list, end_copy_of_mod_objs_list); 1548 1549 /* 1550 * remove the modified objects, and newly objects list 1551 */ 1552 delete_all_objs_in_list(mod_objs_list); 1553 delete_all_objs_in_list(added_objs_list); 1554 return (rv); 1555 } 1556 1557 CK_RV 1558 dup_bigint_attr(biginteger_t *bi, CK_BYTE *buf, CK_ULONG buflen) 1559 { 1560 bi->big_value_len = buflen; 1561 if ((bi->big_value = malloc(buflen)) == NULL) { 1562 return (CKR_HOST_MEMORY); 1563 } 1564 (void) memcpy(bi->big_value, buf, buflen); 1565 return (CKR_OK); 1566 } 1567