/* * Common Public License Version 0.5 * * THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF * THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, * REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES * RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. * * 1. DEFINITIONS * * "Contribution" means: * a) in the case of the initial Contributor, the * initial code and documentation distributed under * this Agreement, and * * b) in the case of each subsequent Contributor: * i) changes to the Program, and * ii) additions to the Program; * * where such changes and/or additions to the Program * originate from and are distributed by that * particular Contributor. A Contribution 'originates' * from a Contributor if it was added to the Program * by such Contributor itself or anyone acting on such * Contributor's behalf. Contributions do not include * additions to the Program which: (i) are separate * modules of software distributed in conjunction with * the Program under their own license agreement, and * (ii) are not derivative works of the Program. * * * "Contributor" means any person or entity that distributes * the Program. * * "Licensed Patents " mean patent claims licensable by a * Contributor which are necessarily infringed by the use or * sale of its Contribution alone or when combined with the * Program. * * "Program" means the Contributions distributed in * accordance with this Agreement. * * "Recipient" means anyone who receives the Program under * this Agreement, including all Contributors. * * 2. GRANT OF RIGHTS * * a) Subject to the terms of this Agreement, each * Contributor hereby grants Recipient a * no - exclusive, worldwide, royalt - free copyright * license to reproduce, prepare derivative works of, * publicly display, publicly perform, distribute and * sublicense the Contribution of such Contributor, if * any, and such derivative works, in source code and * object code form. * * b) Subject to the terms of this Agreement, each * Contributor hereby grants Recipient a * no - exclusive, worldwide, royalt - free patent * license under Licensed Patents to make, use, sell, * offer to sell, import and otherwise transfer the * Contribution of such Contributor, if any, in source * code and object code form. This patent license * shall apply to the combination of the Contribution * and the Program if, at the time the Contribution is * added by the Contributor, such addition of the * Contribution causes such combination to be covered * by the Licensed Patents. The patent license shall * not apply to any other combinations which include * the Contribution. No hardware per se is licensed * hereunder. * * c) Recipient understands that although each * Contributor grants the licenses to its * Contributions set forth herein, no assurances are * provided by any Contributor that the Program does * not infringe the patent or other intellectual * property rights of any other entity. Each * Contributor disclaims any liability to Recipient * for claims brought by any other entity based on * infringement of intellectual property rights or * otherwise. As a condition to exercising the rights * and licenses granted hereunder, each Recipient * hereby assumes sole responsibility to secure any * other intellectual property rights needed, if any. * * For example, if a third party patent license is * required to allow Recipient to distribute the * Program, it is Recipient's responsibility to * acquire that license before distributing the * Program. * * d) Each Contributor represents that to its * knowledge it has sufficient copyright rights in its * Contribution, if any, to grant the copyright * license set forth in this Agreement. * * 3. REQUIREMENTS * * A Contributor may choose to distribute the Program in * object code form under its own license agreement, provided * that: * a) it complies with the terms and conditions of * this Agreement; and * * b) its license agreement: * i) effectively disclaims on behalf of all * Contributors all warranties and conditions, express * and implied, including warranties or conditions of * title and no - infringement, and implied warranties * or conditions of merchantability and fitness for a * particular purpose; * * ii) effectively excludes on behalf of all * Contributors all liability for damages, including * direct, indirect, special, incidental and * consequential damages, such as lost profits; * * iii) states that any provisions which differ from * this Agreement are offered by that Contributor * alone and not by any other party; and * * iv) states that source code for the Program is * available from such Contributor, and informs * licensees how to obtain it in a reasonable manner * on or through a medium customarily used for * software exchange. * * When the Program is made available in source code form: * a) it must be made available under this Agreement; * and * b) a copy of this Agreement must be included with * each copy of the Program. * * Contributors may not remove or alter any copyright notices * contained within the Program. * * Each Contributor must identify itself as the originator of * its Contribution, if any, in a manner that reasonably * allows subsequent Recipients to identify the originator of * the Contribution. * * * 4. COMMERCIAL DISTRIBUTION * * Commercial distributors of software may accept certain * responsibilities with respect to end users, business * partners and the like. While this license is intended to * facilitate the commercial use of the Program, the * Contributor who includes the Program in a commercial * product offering should do so in a manner which does not * create potential liability for other Contributors. * Therefore, if a Contributor includes the Program in a * commercial product offering, such Contributor ("Commercial * Contributor") hereby agrees to defend and indemnify every * other Contributor ("Indemnified Contributor") against any * losses, damages and costs (collectively "Losses") arising * from claims, lawsuits and other legal actions brought by a * third party against the Indemnified Contributor to the * extent caused by the acts or omissions of such Commercial * Contributor in connection with its distribution of the * Program in a commercial product offering. The obligations * in this section do not apply to any claims or Losses * relating to any actual or alleged intellectual property * infringement. In order to qualify, an Indemnified * Contributor must: a) promptly notify the Commercial * Contributor in writing of such claim, and b) allow the * Commercial Contributor to control, and cooperate with the * Commercial Contributor in, the defense and any related * settlement negotiations. The Indemnified Contributor may * participate in any such claim at its own expense. * * * For example, a Contributor might include the Program in a * commercial product offering, Product X. That Contributor * is then a Commercial Contributor. If that Commercial * Contributor then makes performance claims, or offers * warranties related to Product X, those performance claims * and warranties are such Commercial Contributor's * responsibility alone. Under this section, the Commercial * Contributor would have to defend claims against the other * Contributors related to those performance claims and * warranties, and if a court requires any other Contributor * to pay any damages as a result, the Commercial Contributor * must pay those damages. * * * 5. NO WARRANTY * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE * PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR * IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR * CONDITIONS OF TITLE, NO - INFRINGEMENT, MERCHANTABILITY OR * FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely * responsible for determining the appropriateness of using * and distributing the Program and assumes all risks * associated with its exercise of rights under this * Agreement, including but not limited to the risks and * costs of program errors, compliance with applicable laws, * damage to or loss of data, programs or equipment, and * unavailability or interruption of operations. * * 6. DISCLAIMER OF LIABILITY * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER * RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION * LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE * OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * 7. GENERAL * * If any provision of this Agreement is invalid or * unenforceable under applicable law, it shall not affect * the validity or enforceability of the remainder of the * terms of this Agreement, and without further action by the * parties hereto, such provision shall be reformed to the * minimum extent necessary to make such provision valid and * enforceable. * * * If Recipient institutes patent litigation against a * Contributor with respect to a patent applicable to * software (including a cros - claim or counterclaim in a * lawsuit), then any patent licenses granted by that * Contributor to such Recipient under this Agreement shall * terminate as of the date such litigation is filed. In * addition, If Recipient institutes patent litigation * against any entity (including a cros - claim or * counterclaim in a lawsuit) alleging that the Program * itself (excluding combinations of the Program with other * software or hardware) infringes such Recipient's * patent(s), then such Recipient's rights granted under * Section 2(b) shall terminate as of the date such * litigation is filed. * * All Recipient's rights under this Agreement shall * terminate if it fails to comply with any of the material * terms or conditions of this Agreement and does not cure * such failure in a reasonable period of time after becoming * aware of such noncompliance. If all Recipient's rights * under this Agreement terminate, Recipient agrees to cease * use and distribution of the Program as soon as reasonably * practicable. However, Recipient's obligations under this * Agreement and any licenses granted by Recipient relating * to the Program shall continue and survive. * * Everyone is permitted to copy and distribute copies of * this Agreement, but in order to avoid inconsistency the * Agreement is copyrighted and may only be modified in the * following manner. The Agreement Steward reserves the right * to publish new versions (including revisions) of this * Agreement from time to time. No one other than the * Agreement Steward has the right to modify this Agreement. * * IBM is the initial Agreement Steward. IBM may assign the * responsibility to serve as the Agreement Steward to a * suitable separate entity. Each new version of the * Agreement will be given a distinguishing version number. * The Program (including Contributions) may always be * distributed subject to the version of the Agreement under * which it was received. In addition, after a new version of * the Agreement is published, Contributor may elect to * distribute the Program (including its Contributions) under * the new version. Except as expressly stated in Sections * 2(a) and 2(b) above, Recipient receives no rights or * licenses to the intellectual property of any Contributor * under this Agreement, whether expressly, by implication, * estoppel or otherwise. All rights in the Program not * expressly granted under this Agreement are reserved. * * * This Agreement is governed by the laws of the State of New * York and the intellectual property laws of the United * States of America. No party to this Agreement will bring a * legal action under this Agreement more than one year after * the cause of action arose. Each party waives its rights to * a jury trial in any resulting litigation. * * * * (C) COPYRIGHT International Business Machines Corp. 2001, 2002 */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include "tpmtok_int.h" pthread_rwlock_t obj_list_rw_mutex = PTHREAD_RWLOCK_INITIALIZER; static CK_RV object_mgr_search_shm_for_obj(TOK_OBJ_ENTRY *, CK_ULONG, CK_ULONG, OBJECT *, CK_ULONG *); static CK_RV object_mgr_update_from_shm(TSS_HCONTEXT); static CK_RV object_mgr_check_shm(TSS_HCONTEXT, OBJECT *); static CK_RV check_object_access(SESSION *sess, OBJECT *o) { CK_BBOOL sess_obj, priv_obj; CK_RV rc = CKR_OK; /* * check whether session has permissions to create the object, etc * * Object R/O R/W R/O R/W R/W * Type Public Public User User SO * ------------------------------------------------------------- * Public session R/W R/W R/W R/W R/W * Private session R/W R/W * Public token R/O R/W R/O R/W R/W * Private token R/O R/W */ sess_obj = object_is_session_object(o); priv_obj = object_is_private(o); if (sess->session_info.state == CKS_RO_PUBLIC_SESSION) { if (priv_obj) { rc = CKR_USER_NOT_LOGGED_IN; goto done; } if (!sess_obj) { rc = CKR_SESSION_READ_ONLY; goto done; } } if (sess->session_info.state == CKS_RO_USER_FUNCTIONS) { if (! sess_obj) { rc = CKR_SESSION_READ_ONLY; goto done; } } if (sess->session_info.state == CKS_RW_PUBLIC_SESSION) { if (priv_obj) { rc = CKR_USER_NOT_LOGGED_IN; goto done; } } if (sess->session_info.state == CKS_RW_SO_FUNCTIONS) { if (priv_obj) { rc = CKR_USER_NOT_LOGGED_IN; goto done; } } done: return (rc); } CK_RV object_mgr_add(SESSION * sess, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE * handle) { OBJECT * o = NULL; CK_BBOOL priv_obj, sess_obj; CK_RV rc; if (! sess || ! pTemplate || ! handle) { return (CKR_FUNCTION_FAILED); } rc = pthread_mutex_lock(&obj_list_mutex); if (rc != CKR_OK) return (CKR_FUNCTION_FAILED); rc = object_create(pTemplate, ulCount, &o); if (rc != CKR_OK) { goto done; } rc = check_object_access(sess, o); if (rc != CKR_OK) goto done; /* * okay, object is created and the session permissions look okay. * add the object to the appropriate list and assign an object handle */ sess_obj = object_is_session_object(o); priv_obj = object_is_private(o); if (sess_obj) { o->session = sess; (void) memset(o->name, 0x00, sizeof (CK_BYTE) * 8); sess_obj_list = dlist_add_as_first(sess_obj_list, o); } else { CK_BYTE current[8]; CK_BYTE next[8]; rc = XProcLock(xproclock); if (rc != CKR_OK) { goto done; } else { if (priv_obj) { if (global_shm->num_priv_tok_obj >= MAX_TOK_OBJS) { rc = CKR_HOST_MEMORY; (void) XProcUnLock(xproclock); goto done; } } else { if (global_shm->num_publ_tok_obj >= MAX_TOK_OBJS) { rc = CKR_HOST_MEMORY; (void) XProcUnLock(xproclock); goto done; } } (void) memcpy(current, &nv_token_data->next_token_object_name, 8); o->session = NULL; (void) memcpy(&o->name, current, 8); (void) compute_next_token_obj_name(current, next); (void) memcpy(&nv_token_data->next_token_object_name, next, 8); rc = save_token_object(sess->hContext, o); if (rc != CKR_OK) { (void) XProcUnLock(xproclock); goto done; } (void) object_mgr_add_to_shm(o); (void) XProcUnLock(xproclock); (void) save_token_data(nv_token_data); } if (priv_obj) priv_token_obj_list = dlist_add_as_last(priv_token_obj_list, o); else publ_token_obj_list = dlist_add_as_last(publ_token_obj_list, o); } rc = object_mgr_add_to_map(sess, o, handle); if (rc != CKR_OK) { DL_NODE *node = NULL; if (sess_obj) { node = dlist_find(sess_obj_list, o); if (node) sess_obj_list = dlist_remove_node(sess_obj_list, node); } else { (void) delete_token_object(o); if (priv_obj) { node = dlist_find(priv_token_obj_list, o); if (node) priv_token_obj_list = dlist_remove_node( priv_token_obj_list, node); } else { node = dlist_find(publ_token_obj_list, o); if (node) publ_token_obj_list = dlist_remove_node( publ_token_obj_list, node); } rc = XProcLock(xproclock); if (rc != CKR_OK) { goto done; } (void) object_mgr_del_from_shm(o); (void) XProcUnLock(xproclock); } } done: (void) pthread_mutex_unlock(&obj_list_mutex); if ((rc != CKR_OK) && (o != NULL)) (void) object_free(o); return (rc); } CK_RV object_mgr_add_to_map(SESSION * sess, OBJECT * obj, CK_OBJECT_HANDLE * handle) { OBJECT_MAP *map_node = NULL; if (! sess || ! obj || ! handle) { return (CKR_FUNCTION_FAILED); } map_node = (OBJECT_MAP *)malloc(sizeof (OBJECT_MAP)); if (! map_node) { return (CKR_HOST_MEMORY); } map_node->handle = next_object_handle++; map_node->session = sess; map_node->ptr = obj; if (obj->session != NULL) map_node->is_session_obj = TRUE; else map_node->is_session_obj = FALSE; // add the new map entry to the list if (pthread_rwlock_wrlock(&obj_list_rw_mutex)) { return (CKR_FUNCTION_FAILED); } object_map = dlist_add_as_first(object_map, map_node); (void) pthread_rwlock_unlock(&obj_list_rw_mutex); *handle = map_node->handle; return (CKR_OK); } // object_mgr_copy() // // algorithm: // 1) find the old object // 2) get the template from the old object // 3) merge in the new object's template // 4) perform class - specific sanity checks // CK_RV object_mgr_copy(SESSION * sess, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE old_handle, CK_OBJECT_HANDLE * new_handle) { OBJECT *old_obj = NULL; OBJECT *new_obj = NULL; CK_BBOOL priv_obj; CK_BBOOL sess_obj; CK_RV rc; if (! sess || ! pTemplate || ! new_handle) { return (CKR_FUNCTION_FAILED); } rc = pthread_mutex_lock(&obj_list_mutex); if (rc != CKR_OK) return (CKR_FUNCTION_FAILED); rc = object_mgr_find_in_map1(sess->hContext, old_handle, &old_obj); if (rc != CKR_OK) { goto done; } rc = object_copy(pTemplate, ulCount, old_obj, &new_obj); if (rc != CKR_OK) { goto done; } rc = check_object_access(sess, new_obj); if (rc != CKR_OK) goto done; sess_obj = object_is_session_object(new_obj); priv_obj = object_is_private(new_obj); if (sess_obj) { new_obj->session = sess; (void) memset(&new_obj->name, 0x00, sizeof (CK_BYTE) * 8); sess_obj_list = dlist_add_as_first(sess_obj_list, new_obj); } else { CK_BYTE current[8]; CK_BYTE next[8]; rc = XProcLock(xproclock); if (rc != CKR_OK) { goto done; } else { if (priv_obj) { if (global_shm->num_priv_tok_obj >= MAX_TOK_OBJS) { (void) XProcUnLock(xproclock); rc = CKR_HOST_MEMORY; goto done; } } else { if (global_shm->num_publ_tok_obj >= MAX_TOK_OBJS) { (void) XProcUnLock(xproclock); rc = CKR_HOST_MEMORY; goto done; } } (void) memcpy(current, &nv_token_data->next_token_object_name, 8); new_obj->session = NULL; (void) memcpy(&new_obj->name, current, 8); (void) compute_next_token_obj_name(current, next); (void) memcpy(&nv_token_data->next_token_object_name, next, 8); rc = save_token_object(sess->hContext, new_obj); if (rc != CKR_OK) { (void) XProcUnLock(xproclock); goto done; } (void) object_mgr_add_to_shm(new_obj); (void) XProcUnLock(xproclock); (void) save_token_data(nv_token_data); } if (priv_obj) priv_token_obj_list = dlist_add_as_last( priv_token_obj_list, new_obj); else publ_token_obj_list = dlist_add_as_last( publ_token_obj_list, new_obj); } rc = object_mgr_add_to_map(sess, new_obj, new_handle); if (rc != CKR_OK) { DL_NODE *node = NULL; if (sess_obj) { node = dlist_find(sess_obj_list, new_obj); if (node) sess_obj_list = dlist_remove_node( sess_obj_list, node); } else { (void) delete_token_object(new_obj); if (priv_obj) { node = dlist_find(priv_token_obj_list, new_obj); if (node) priv_token_obj_list = dlist_remove_node( priv_token_obj_list, node); } else { node = dlist_find(publ_token_obj_list, new_obj); if (node) publ_token_obj_list = dlist_remove_node( publ_token_obj_list, node); } rc = XProcLock(xproclock); if (rc != CKR_OK) { goto done; } (void) object_mgr_del_from_shm(new_obj); (void) XProcUnLock(xproclock); } } done: (void) pthread_mutex_unlock(&obj_list_mutex); if ((rc != CKR_OK) && (new_obj != NULL)) (void) object_free(new_obj); return (rc); } // // determines whether the session is allowed to create an object. creates // the object but doesn't add the object to any object lists or to the // process' object map. // CK_RV object_mgr_create_skel(SESSION * sess, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount, CK_ULONG mode, CK_ULONG obj_type, CK_ULONG sub_class, OBJECT ** obj) { OBJECT *o = NULL; CK_RV rc; CK_BBOOL priv_obj; CK_BBOOL sess_obj; if (! sess || ! obj) { return (CKR_FUNCTION_FAILED); } if (! pTemplate && (ulCount != 0)) { return (CKR_FUNCTION_FAILED); } rc = object_create_skel(pTemplate, ulCount, mode, obj_type, sub_class, &o); if (rc != CKR_OK) { return (rc); } sess_obj = object_is_session_object(o); priv_obj = object_is_private(o); if (sess->session_info.state == CKS_RO_PUBLIC_SESSION) { if (priv_obj) { (void) object_free(o); return (CKR_USER_NOT_LOGGED_IN); } if (! sess_obj) { (void) object_free(o); return (CKR_SESSION_READ_ONLY); } } if (sess->session_info.state == CKS_RO_USER_FUNCTIONS) { if (! sess_obj) { (void) object_free(o); return (CKR_SESSION_READ_ONLY); } } if (sess->session_info.state == CKS_RW_PUBLIC_SESSION) { if (priv_obj) { (void) object_free(o); return (CKR_USER_NOT_LOGGED_IN); } } if (sess->session_info.state == CKS_RW_SO_FUNCTIONS) { if (priv_obj) { (void) object_free(o); return (CKR_USER_NOT_LOGGED_IN); } } *obj = o; return (CKR_OK); } CK_RV object_mgr_create_final(SESSION * sess, OBJECT * obj, CK_OBJECT_HANDLE * handle) { CK_BBOOL sess_obj; CK_BBOOL priv_obj; CK_RV rc; if (!sess || !obj || !handle) return (CKR_FUNCTION_FAILED); rc = pthread_mutex_lock(&obj_list_mutex); if (rc != CKR_OK) return (CKR_FUNCTION_FAILED); sess_obj = object_is_session_object(obj); priv_obj = object_is_private(obj); if (sess_obj) { obj->session = sess; (void) memset(obj->name, 0x0, sizeof (CK_BYTE) * 8); sess_obj_list = dlist_add_as_first(sess_obj_list, obj); } else { CK_BYTE current[8]; CK_BYTE next[8]; rc = XProcLock(xproclock); if (rc != CKR_OK) { goto done; } else { if (priv_obj) { if (global_shm->num_priv_tok_obj >= MAX_TOK_OBJS) { (void) XProcUnLock(xproclock); rc = CKR_HOST_MEMORY; goto done; } } else { if (global_shm->num_publ_tok_obj >= MAX_TOK_OBJS) { (void) XProcUnLock(xproclock); rc = CKR_HOST_MEMORY; goto done; } } (void) memcpy(current, &nv_token_data->next_token_object_name, 8); obj->session = NULL; (void) memcpy(&obj->name, current, 8); (void) compute_next_token_obj_name(current, next); (void) memcpy(&nv_token_data->next_token_object_name, next, 8); rc = save_token_object(sess->hContext, obj); if (rc != CKR_OK) { (void) XProcUnLock(xproclock); goto done; } (void) object_mgr_add_to_shm(obj); (void) XProcUnLock(xproclock); (void) save_token_data(nv_token_data); } if (priv_obj) priv_token_obj_list = dlist_add_as_last( priv_token_obj_list, obj); else publ_token_obj_list = dlist_add_as_last( publ_token_obj_list, obj); } rc = object_mgr_add_to_map(sess, obj, handle); if (rc != CKR_OK) { DL_NODE *node = NULL; if (sess_obj) { node = dlist_find(sess_obj_list, obj); if (node) sess_obj_list = dlist_remove_node( sess_obj_list, node); } else { (void) delete_token_object(obj); if (priv_obj) { node = dlist_find(priv_token_obj_list, obj); if (node) priv_token_obj_list = dlist_remove_node( priv_token_obj_list, node); } else { node = dlist_find(publ_token_obj_list, obj); if (node) publ_token_obj_list = dlist_remove_node( publ_token_obj_list, node); } rc = XProcLock(xproclock); if (rc != CKR_OK) { goto done; } (void) object_mgr_del_from_shm(obj); (void) XProcUnLock(xproclock); } } done: (void) pthread_mutex_unlock(&obj_list_mutex); return (rc); } CK_RV object_mgr_destroy_object(SESSION * sess, CK_OBJECT_HANDLE handle) { OBJECT * obj = NULL; CK_BBOOL sess_obj; CK_BBOOL priv_obj; CK_RV rc; if (! sess) return (CKR_FUNCTION_FAILED); rc = pthread_mutex_lock(&obj_list_mutex); if (rc != CKR_OK) return (CKR_FUNCTION_FAILED); rc = object_mgr_find_in_map1(sess->hContext, handle, &obj); if (rc != CKR_OK) { goto done; } rc = check_object_access(sess, obj); if (rc != CKR_OK) goto done; sess_obj = object_is_session_object(obj); priv_obj = object_is_private(obj); if (sess_obj) { DL_NODE *node; node = dlist_find(sess_obj_list, obj); if (node) { (void) object_mgr_remove_from_map(handle); (void) object_free(obj); sess_obj_list = dlist_remove_node( sess_obj_list, node); rc = CKR_OK; goto done; } } else { DL_NODE *node = NULL; (void) delete_token_object(obj); if (priv_obj) node = dlist_find(priv_token_obj_list, obj); else node = dlist_find(publ_token_obj_list, obj); if (node) { rc = XProcLock(xproclock); if (rc != CKR_OK) { goto done; } (void) object_mgr_del_from_shm(obj); (void) XProcUnLock(xproclock); (void) object_mgr_remove_from_map(handle); (void) object_free(obj); if (priv_obj) priv_token_obj_list = dlist_remove_node( priv_token_obj_list, node); else publ_token_obj_list = dlist_remove_node( publ_token_obj_list, node); rc = CKR_OK; goto done; } } rc = CKR_FUNCTION_FAILED; done: (void) pthread_mutex_unlock(&obj_list_mutex); return (rc); } CK_RV object_mgr_destroy_token_objects(TSS_HCONTEXT hContext) { CK_BBOOL locked2 = FALSE; CK_RV rc; rc = pthread_mutex_lock(&obj_list_mutex); if (rc != CKR_OK) return (CKR_FUNCTION_FAILED); while (publ_token_obj_list) { OBJECT *obj = (OBJECT *)publ_token_obj_list->data; CK_OBJECT_HANDLE handle; rc = object_mgr_find_in_map2(hContext, obj, &handle); if (rc == CKR_OK) { (void) object_mgr_remove_from_map(handle); } (void) delete_token_object(obj); (void) object_free(obj); publ_token_obj_list = dlist_remove_node( publ_token_obj_list, publ_token_obj_list); } while (priv_token_obj_list) { OBJECT *obj = (OBJECT *)priv_token_obj_list->data; CK_OBJECT_HANDLE handle; rc = object_mgr_find_in_map2(hContext, obj, &handle); if (rc == CKR_OK) { (void) object_mgr_remove_from_map(handle); } (void) delete_token_object(obj); (void) object_free(obj); priv_token_obj_list = dlist_remove_node( priv_token_obj_list, priv_token_obj_list); } // now we want to purge the token object list in shared memory // rc = XProcLock(xproclock); if (rc == CKR_OK) { locked2 = TRUE; global_shm->num_priv_tok_obj = 0; global_shm->num_publ_tok_obj = 0; (void) memset(&global_shm->publ_tok_objs, 0x0, MAX_TOK_OBJS * sizeof (TOK_OBJ_ENTRY)); (void) memset(&global_shm->priv_tok_objs, 0x0, MAX_TOK_OBJS * sizeof (TOK_OBJ_ENTRY)); } done: (void) pthread_mutex_unlock(&obj_list_mutex); if (locked2 == TRUE) (void) XProcUnLock(xproclock); return (rc); } // // Locates the specified object in the map // without going and checking for cache update // CK_RV object_mgr_find_in_map_nocache(CK_OBJECT_HANDLE handle, OBJECT ** ptr) { DL_NODE * node = NULL; OBJECT * obj = NULL; if (! ptr) { return (CKR_FUNCTION_FAILED); } if (pthread_rwlock_rdlock(&obj_list_rw_mutex)) { return (CKR_FUNCTION_FAILED); } node = object_map; while (node) { OBJECT_MAP *map = (OBJECT_MAP *)node->data; if (map->handle == handle) { obj = map->ptr; break; } node = node->next; } (void) pthread_rwlock_unlock(&obj_list_rw_mutex); if (obj == NULL || node == NULL) { return (CKR_OBJECT_HANDLE_INVALID); } if (object_is_session_object(obj) == TRUE) { *ptr = obj; return (CKR_OK); } *ptr = obj; return (CKR_OK); } CK_RV object_mgr_find_in_map1( TSS_HCONTEXT hContext, CK_OBJECT_HANDLE handle, OBJECT ** ptr) { DL_NODE * node = NULL; OBJECT * obj = NULL; if (! ptr) { return (CKR_FUNCTION_FAILED); } if (pthread_rwlock_rdlock(&obj_list_rw_mutex)) { return (CKR_FUNCTION_FAILED); } node = object_map; while (node) { OBJECT_MAP *map = (OBJECT_MAP *)node->data; if (map->handle == handle) { obj = map->ptr; break; } node = node->next; } (void) pthread_rwlock_unlock(&obj_list_rw_mutex); if (obj == NULL || node == NULL) { return (CKR_OBJECT_HANDLE_INVALID); } if (object_is_session_object(obj) == TRUE) { *ptr = obj; return (CKR_OK); } (void) object_mgr_check_shm(hContext, obj); *ptr = obj; return (CKR_OK); } CK_RV object_mgr_find_in_map2( TSS_HCONTEXT hContext, OBJECT * obj, CK_OBJECT_HANDLE * handle) { DL_NODE * node = NULL; CK_OBJECT_HANDLE h = (CK_OBJECT_HANDLE)NULL; if (! obj || ! handle) { return (CKR_FUNCTION_FAILED); } if (pthread_rwlock_rdlock(&obj_list_rw_mutex)) { return (CKR_FUNCTION_FAILED); } node = object_map; while (node) { OBJECT_MAP *map = (OBJECT_MAP *)node->data; if (map->ptr == obj) { h = map->handle; break; } node = node->next; } (void) pthread_rwlock_unlock(&obj_list_rw_mutex); if (node == NULL) { return (CKR_OBJECT_HANDLE_INVALID); } if (object_is_session_object(obj) == TRUE) { *handle = h; return (CKR_OK); } (void) object_mgr_check_shm(hContext, obj); *handle = h; return (CKR_OK); } CK_RV object_mgr_find_init(SESSION * sess, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount) { if (! sess) { return (CKR_FUNCTION_FAILED); } if (sess->find_active != FALSE) { return (CKR_OPERATION_ACTIVE); } // initialize the found object list. if it doesn't exist, allocate // a list big enough for 10 handles. we'll reallocate if we need more // if (sess->find_list != NULL) { (void) memset(sess->find_list, 0x0, sess->find_len * sizeof (CK_OBJECT_HANDLE)); } else { sess->find_list = (CK_OBJECT_HANDLE *)malloc( 10 * sizeof (CK_OBJECT_HANDLE)); if (! sess->find_list) { return (CKR_HOST_MEMORY); } else { (void) memset(sess->find_list, 0x0, 10 * sizeof (CK_OBJECT_HANDLE)); sess->find_len = 10; } } sess->find_count = 0; sess->find_idx = 0; // --- need to grab the object lock here if (pthread_mutex_lock(&obj_list_mutex)) return (CKR_FUNCTION_FAILED); (void) object_mgr_update_from_shm(sess->hContext); // which objects can be return (ed: // // Public Session: public session objects, public token objects // User Session: all session objects, all token objects // SO session: public session objects, public token objects // switch (sess->session_info.state) { case CKS_RO_PUBLIC_SESSION: case CKS_RW_PUBLIC_SESSION: case CKS_RW_SO_FUNCTIONS: (void) object_mgr_find_build_list(sess, pTemplate, ulCount, publ_token_obj_list, TRUE); (void) object_mgr_find_build_list(sess, pTemplate, ulCount, sess_obj_list, TRUE); break; case CKS_RO_USER_FUNCTIONS: case CKS_RW_USER_FUNCTIONS: (void) object_mgr_find_build_list(sess, pTemplate, ulCount, priv_token_obj_list, FALSE); (void) object_mgr_find_build_list(sess, pTemplate, ulCount, publ_token_obj_list, FALSE); (void) object_mgr_find_build_list(sess, pTemplate, ulCount, sess_obj_list, FALSE); break; } (void) pthread_mutex_unlock(&obj_list_mutex); sess->find_active = TRUE; return (CKR_OK); } CK_RV object_mgr_find_build_list(SESSION * sess, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount, DL_NODE * obj_list, CK_BBOOL public_only) { OBJECT * obj = NULL; DL_NODE * node = NULL; CK_OBJECT_HANDLE handle; CK_BBOOL is_priv; CK_BBOOL match; CK_BBOOL hw_feature = FALSE; CK_BBOOL hidden_object = FALSE; CK_RV rc; CK_ATTRIBUTE * attr; unsigned int i; if (! sess) { return (CKR_FUNCTION_FAILED); } if (! obj_list) return (CKR_OK); // PKCS#11 v2.11 (pg. 79): "When searching using C_FindObjectsInit // and C_FindObjects, hardware feature objects are not returned // unless the CKA_CLASS attribute in the template has the value // CKO_HW_FEATURE." So, we check for CKO_HW_FEATURE and if its set, // we'll find these objects below. - KEY for (i = 0; i < ulCount; i++) { if (pTemplate[i].type == CKA_CLASS) { if (*(CK_ULONG *)pTemplate[i].pValue == CKO_HW_FEATURE) { hw_feature = TRUE; break; } } if (pTemplate[i].type == CKA_HIDDEN) { if (*(CK_BBOOL *)pTemplate[i].pValue == TRUE) { hidden_object = TRUE; break; } } } node = obj_list; while (node) { match = FALSE; obj = (OBJECT *)node->data; is_priv = object_is_private(obj); if ((is_priv == FALSE) || (public_only == FALSE)) { if (pTemplate == NULL || ulCount == 0) match = TRUE; else match = template_compare(pTemplate, ulCount, obj->template); } if (match) { rc = object_mgr_find_in_map2(sess->hContext, obj, &handle); if (rc != CKR_OK) { rc = object_mgr_add_to_map(sess, obj, &handle); if (rc != CKR_OK) { return (CKR_FUNCTION_FAILED); } } if (rc == CKR_OK) { if ((hw_feature == FALSE) && (template_attribute_find(obj->template, CKA_CLASS, &attr) == TRUE)) { if (*(CK_OBJECT_CLASS *)attr->pValue == CKO_HW_FEATURE) goto next_loop; } if ((hidden_object == FALSE) && (template_attribute_find(obj->template, CKA_HIDDEN, &attr) == TRUE)) { if (*(CK_BBOOL *)attr->pValue == TRUE) goto next_loop; } sess->find_list[ sess->find_count ] = handle; sess->find_count++; if (sess->find_count >= sess->find_len) { sess->find_len += 15; sess->find_list = (CK_OBJECT_HANDLE *)realloc( sess->find_list, sess->find_len * sizeof (CK_OBJECT_HANDLE)); if (! sess->find_list) { return (CKR_HOST_MEMORY); } } } } next_loop: node = node->next; } return (CKR_OK); } CK_RV object_mgr_find_final(SESSION *sess) { if (! sess) { return (CKR_FUNCTION_FAILED); } if (sess->find_active == FALSE) { return (CKR_OPERATION_NOT_INITIALIZED); } free(sess->find_list); sess->find_list = NULL; sess->find_count = 0; sess->find_idx = 0; sess->find_active = FALSE; return (CKR_OK); } CK_RV object_mgr_get_attribute_values(SESSION * sess, CK_OBJECT_HANDLE handle, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount) { OBJECT * obj; CK_BBOOL priv_obj; CK_RV rc; if (! pTemplate) { return (CKR_FUNCTION_FAILED); } rc = pthread_mutex_lock(&obj_list_mutex); if (rc != CKR_OK) return (CKR_FUNCTION_FAILED); rc = object_mgr_find_in_map1(sess->hContext, handle, &obj); if (rc != CKR_OK) { goto done; } priv_obj = object_is_private(obj); if (priv_obj == TRUE) { if (sess->session_info.state == CKS_RO_PUBLIC_SESSION || sess->session_info.state == CKS_RW_PUBLIC_SESSION) { rc = CKR_USER_NOT_LOGGED_IN; goto done; } } rc = object_get_attribute_values(obj, pTemplate, ulCount); done: (void) pthread_mutex_unlock(&obj_list_mutex); return (rc); } CK_RV object_mgr_get_object_size( TSS_HCONTEXT hContext, CK_OBJECT_HANDLE handle, CK_ULONG * size) { OBJECT * obj; CK_RV rc; rc = pthread_mutex_lock(&obj_list_mutex); if (rc != CKR_OK) return (CKR_FUNCTION_FAILED); rc = object_mgr_find_in_map1(hContext, handle, &obj); if (rc != CKR_OK) { rc = CKR_OBJECT_HANDLE_INVALID; goto done; } *size = object_get_size(obj); done: (void) pthread_mutex_unlock(&obj_list_mutex); return (rc); } // object_mgr_invalidate_handle1() // // Returns: TRUE if successfully removes the node // FALSE if cannot remove the node (not found, etc) // CK_BBOOL object_mgr_invalidate_handle1(CK_OBJECT_HANDLE handle) { DL_NODE *node = NULL; if (pthread_rwlock_wrlock(&obj_list_rw_mutex)) { return (CKR_FUNCTION_FAILED); } node = object_map; while (node) { OBJECT_MAP *map = (OBJECT_MAP *)node->data; if (map->handle == handle) { object_map = dlist_remove_node(object_map, node); free(map); (void) pthread_rwlock_unlock(&obj_list_rw_mutex); return (TRUE); } node = node->next; } (void) pthread_rwlock_unlock(&obj_list_rw_mutex); return (FALSE); } // object_mgr_invalidate_handle2() // // Returns: TRUE if successfully removes the node // FALSE if cannot remove the node (not found, etc) // CK_BBOOL object_mgr_invalidate_handle2(OBJECT *obj) { DL_NODE *node = NULL; if (! obj) return (FALSE); if (pthread_rwlock_wrlock(&obj_list_rw_mutex)) { return (CKR_FUNCTION_FAILED); } node = object_map; while (node) { OBJECT_MAP *map = (OBJECT_MAP *)node->data; if (map->ptr == obj) { object_map = dlist_remove_node(object_map, node); free(map); (void) pthread_rwlock_unlock(&obj_list_rw_mutex); return (TRUE); } node = node->next; } (void) pthread_rwlock_unlock(&obj_list_rw_mutex); return (FALSE); } // object_mgr_purge_session_objects() // // Args: SESSION * // SESS_OBJ_TYPE: can be ALL, PRIVATE or PUBLIC // // Remove all session objects owned by the specified session satisfying // the 'type' requirements // CK_BBOOL object_mgr_purge_session_objects(SESSION * sess, SESS_OBJ_TYPE type) { DL_NODE *node = NULL; DL_NODE *next = NULL; OBJECT *obj = NULL; CK_BBOOL del; CK_RV rc; if (!sess) return (FALSE); rc = pthread_mutex_lock(&obj_list_mutex); if (rc != CKR_OK) return (FALSE); node = sess_obj_list; while (node) { obj = (OBJECT *)node->data; del = FALSE; if (obj->session == sess) { if (type == PRIVATE) { if (object_is_private(obj)) del = TRUE; } else if (type == PUBLIC) { if (object_is_public(obj)) del = TRUE; } else if (type == ALL) del = TRUE; } if (del == TRUE) { CK_OBJECT_HANDLE handle; CK_RV rc; rc = object_mgr_find_in_map2(sess->hContext, obj, &handle); if (rc == CKR_OK) { (void) object_mgr_invalidate_handle1(handle); (void) object_free(obj); } next = node->next; sess_obj_list = dlist_remove_node(sess_obj_list, node); node = next; } else node = node->next; } (void) pthread_mutex_unlock(&obj_list_mutex); return (TRUE); } // // This routine cleans up the list of token objects. in general, we don't // need to do this but when tracing memory leaks, it's best that we free // everything that we've allocated. // CK_BBOOL object_mgr_purge_token_objects(TSS_HCONTEXT hContext) { DL_NODE *node = NULL; DL_NODE *next = NULL; OBJECT *obj = NULL; CK_RV rc; rc = pthread_mutex_lock(&obj_list_mutex); if (rc != CKR_OK) return (FALSE); node = publ_token_obj_list; while (publ_token_obj_list) { CK_OBJECT_HANDLE handle; CK_RV rc; obj = (OBJECT *)node->data; rc = object_mgr_find_in_map2(hContext, obj, &handle); if (rc == CKR_OK) { (void) object_mgr_invalidate_handle1(handle); } (void) object_free(obj); next = node->next; publ_token_obj_list = dlist_remove_node( publ_token_obj_list, node); node = next; } node = priv_token_obj_list; while (priv_token_obj_list) { CK_OBJECT_HANDLE handle; CK_RV rc; obj = (OBJECT *)node->data; rc = object_mgr_find_in_map2(hContext, obj, &handle); if (rc == CKR_OK) (void) object_mgr_invalidate_handle1(handle); (void) object_free(obj); next = node->next; priv_token_obj_list = dlist_remove_node( priv_token_obj_list, node); node = next; } (void) pthread_mutex_unlock(&obj_list_mutex); return (TRUE); } CK_BBOOL object_mgr_purge_private_token_objects(TSS_HCONTEXT hContext) { OBJECT * obj = NULL; DL_NODE * node = NULL; DL_NODE * next = NULL; CK_RV rc; rc = pthread_mutex_lock(&obj_list_mutex); if (rc != CKR_OK) return (FALSE); node = priv_token_obj_list; while (priv_token_obj_list) { CK_OBJECT_HANDLE handle; CK_RV rc; obj = (OBJECT *)node->data; rc = object_mgr_find_in_map2(hContext, obj, &handle); if (rc == CKR_OK) { (void) object_mgr_invalidate_handle1(handle); } (void) object_free(obj); next = node->next; priv_token_obj_list = dlist_remove_node( priv_token_obj_list, node); node = next; } (void) pthread_mutex_unlock(&obj_list_mutex); return (TRUE); } CK_RV object_mgr_remove_from_map(CK_OBJECT_HANDLE handle) { DL_NODE *node = NULL; if (pthread_rwlock_wrlock(&obj_list_rw_mutex)) { return (CKR_FUNCTION_FAILED); } node = object_map; while (node) { OBJECT_MAP *map = (OBJECT_MAP *)node->data; if (map->handle == handle) { object_map = dlist_remove_node(object_map, node); free(map); (void) pthread_rwlock_unlock(&obj_list_rw_mutex); return (CKR_OK); } node = node->next; } (void) pthread_rwlock_unlock(&obj_list_rw_mutex); return (CKR_FUNCTION_FAILED); } CK_RV object_mgr_restore_obj(CK_BYTE *data, OBJECT *oldObj) { OBJECT * obj = NULL; CK_BBOOL priv; CK_RV rc; if (! data) { return (CKR_FUNCTION_FAILED); } if (oldObj != NULL) { obj = oldObj; rc = object_restore(data, &obj, TRUE); } else { rc = object_restore(data, &obj, FALSE); if (rc == CKR_OK) { priv = object_is_private(obj); if (priv) priv_token_obj_list = dlist_add_as_last( priv_token_obj_list, obj); else publ_token_obj_list = dlist_add_as_last( publ_token_obj_list, obj); (void) XProcLock(xproclock); if (priv) { if (global_shm->priv_loaded == FALSE) { if (global_shm->num_priv_tok_obj < MAX_TOK_OBJS) (void) object_mgr_add_to_shm( obj); else rc = CKR_HOST_MEMORY; } } else { if (global_shm->publ_loaded == FALSE) { if (global_shm->num_publ_tok_obj < MAX_TOK_OBJS) (void) object_mgr_add_to_shm( obj); else rc = CKR_HOST_MEMORY; } } (void) XProcUnLock(xproclock); } } // make the callers have to have the mutes // to many grab it now. return (rc); } CK_RV object_mgr_set_attribute_values(SESSION * sess, CK_OBJECT_HANDLE handle, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount) { OBJECT * obj; CK_BBOOL sess_obj, priv_obj; CK_BBOOL modifiable; CK_RV rc; if (! pTemplate) { return (CKR_FUNCTION_FAILED); } rc = pthread_mutex_lock(&obj_list_mutex); if (rc != CKR_OK) return (CKR_FUNCTION_FAILED); rc = object_mgr_find_in_map1(sess->hContext, handle, &obj); if (rc != CKR_OK) { (void) pthread_mutex_unlock(&obj_list_mutex); return (CKR_OBJECT_HANDLE_INVALID); } (void) pthread_mutex_unlock(&obj_list_mutex); modifiable = object_is_modifiable(obj); sess_obj = object_is_session_object(obj); priv_obj = object_is_private(obj); if (! modifiable) { return (CKR_ATTRIBUTE_READ_ONLY); } rc = check_object_access(sess, obj); if (rc != CKR_OK) return (rc); rc = object_set_attribute_values(obj, pTemplate, ulCount); if (rc != CKR_OK) { return (rc); } if (! sess_obj) { TOK_OBJ_ENTRY *entry = NULL; CK_ULONG index; obj->count_lo++; if (obj->count_lo == 0) obj->count_hi++; rc = save_token_object(sess->hContext, obj); if (rc != CKR_OK) return (rc); rc = XProcLock(xproclock); if (rc != CKR_OK) { return (rc); } if (priv_obj) { rc = object_mgr_search_shm_for_obj( global_shm->priv_tok_objs, 0, global_shm->num_priv_tok_obj - 1, obj, &index); if (rc != CKR_OK) { (void) XProcUnLock(xproclock); return (rc); } entry = &global_shm->priv_tok_objs[index]; } else { rc = object_mgr_search_shm_for_obj( global_shm->publ_tok_objs, 0, global_shm->num_publ_tok_obj - 1, obj, &index); if (rc != CKR_OK) { (void) XProcUnLock(xproclock); return (rc); } entry = &global_shm->publ_tok_objs[index]; } entry->count_lo = obj->count_lo; entry->count_hi = obj->count_hi; (void) XProcUnLock(xproclock); } return (rc); } CK_RV object_mgr_add_to_shm(OBJECT *obj) { TOK_OBJ_ENTRY * entry = NULL; CK_BBOOL priv; priv = object_is_private(obj); if (priv) entry = &global_shm->priv_tok_objs[ global_shm->num_priv_tok_obj]; else entry = &global_shm->publ_tok_objs[ global_shm->num_publ_tok_obj]; entry->deleted = FALSE; entry->count_lo = 0; entry->count_hi = 0; (void) memcpy(entry->name, obj->name, 8); if (priv) { global_shm->num_priv_tok_obj++; } else { global_shm->num_publ_tok_obj++; } return (CKR_OK); } CK_RV object_mgr_del_from_shm(OBJECT *obj) { CK_ULONG index, count; CK_BBOOL priv; CK_RV rc; priv = object_is_private(obj); if (priv) { rc = object_mgr_search_shm_for_obj(global_shm->priv_tok_objs, 0, global_shm->num_priv_tok_obj - 1, obj, &index); if (rc != CKR_OK) { return (CKR_FUNCTION_FAILED); } global_shm->num_priv_tok_obj--; if (index > global_shm->num_priv_tok_obj) { count = index - global_shm->num_priv_tok_obj; } else { count = global_shm->num_priv_tok_obj - index; } if (count > 0) { (void) memcpy((char *)&global_shm->priv_tok_objs[index], (char *)&global_shm->priv_tok_objs[index + 1], sizeof (TOK_OBJ_ENTRY) * count); (void) memset((char *)&global_shm->priv_tok_objs[ global_shm->num_priv_tok_obj + 1], 0, sizeof (TOK_OBJ_ENTRY)); } else { (void) memset((char *)&global_shm->priv_tok_objs[ global_shm->num_priv_tok_obj], 0, sizeof (TOK_OBJ_ENTRY)); } } else { rc = object_mgr_search_shm_for_obj(global_shm->publ_tok_objs, 0, global_shm->num_publ_tok_obj - 1, obj, &index); if (rc != CKR_OK) { return (CKR_FUNCTION_FAILED); } global_shm->num_publ_tok_obj--; if (index > global_shm->num_publ_tok_obj) { count = index - global_shm->num_publ_tok_obj; } else { count = global_shm->num_publ_tok_obj - index; } if (count > 0) { (void) memcpy((char *)&global_shm->publ_tok_objs[index], (char *)&global_shm->publ_tok_objs[index + 1], sizeof (TOK_OBJ_ENTRY) * count); (void) memset((char *)&global_shm->publ_tok_objs[ global_shm->num_publ_tok_obj + 1], 0, sizeof (TOK_OBJ_ENTRY)); } else { (void) memset((char *)&global_shm->publ_tok_objs[ global_shm->num_publ_tok_obj], 0, sizeof (TOK_OBJ_ENTRY)); } } return (CKR_OK); } static CK_RV object_mgr_check_shm(TSS_HCONTEXT hContext, OBJECT *obj) { TOK_OBJ_ENTRY * entry = NULL; CK_BBOOL priv; CK_ULONG index; CK_RV rc; priv = object_is_private(obj); if (priv) { rc = object_mgr_search_shm_for_obj( global_shm->priv_tok_objs, 0, global_shm->num_priv_tok_obj - 1, obj, &index); if (rc != CKR_OK) { return (CKR_FUNCTION_FAILED); } entry = &global_shm->priv_tok_objs[index]; } else { rc = object_mgr_search_shm_for_obj( global_shm->publ_tok_objs, 0, global_shm->num_publ_tok_obj - 1, obj, &index); if (rc != CKR_OK) { return (CKR_FUNCTION_FAILED); } entry = &global_shm->publ_tok_objs[index]; } if ((obj->count_hi == entry->count_hi) && (obj->count_lo == entry->count_lo)) return (CKR_OK); rc = reload_token_object(hContext, obj); return (rc); } /*ARGSUSED*/ static CK_RV object_mgr_search_shm_for_obj( TOK_OBJ_ENTRY *obj_list, CK_ULONG lo, CK_ULONG hi, OBJECT *obj, CK_ULONG *index) { CK_ULONG idx; if (obj->index == 0) { for (idx = lo; idx <= hi; idx++) { if (memcmp(obj->name, obj_list[idx].name, 8) == 0) { *index = idx; obj->index = idx; return (CKR_OK); } } } else { if (memcmp(obj->name, obj_list[obj->index].name, 8) == 0) { *index = obj->index; return (CKR_OK); } else { for (idx = lo; idx <= hi; idx++) { if (memcmp(obj->name, obj_list[idx].name, 8) == 0) { *index = idx; obj->index = idx; return (CKR_OK); } } } } return (CKR_FUNCTION_FAILED); } static CK_RV object_mgr_update_publ_tok_obj_from_shm(TSS_HCONTEXT hContext) { DL_NODE * node = NULL; DL_NODE * next = NULL; TOK_OBJ_ENTRY * te = NULL; OBJECT * obj = NULL; CK_OBJECT_HANDLE handle; CK_ULONG index; int val; CK_RV rc; node = publ_token_obj_list; index = 0; while ((node != NULL) && (index < global_shm->num_publ_tok_obj)) { te = &global_shm->publ_tok_objs[index]; obj = (OBJECT *)node->data; val = memcmp(obj->name, te->name, 8); // 3 cases: // 1) object in local list but not in the global list, // need to remove from local list // 2) object in both lists, need to compare counters // and update as needed // 3) object in global list but not in the local list, // need to add the object here. // if (val < 0) { rc = object_mgr_find_in_map2(hContext, obj, &handle); if (rc == CKR_OK) { (void) object_mgr_remove_from_map(handle); } (void) object_free(obj); next = node->next; publ_token_obj_list = dlist_remove_node( publ_token_obj_list, node); } else if (val == 0) { if ((te->count_hi != obj->count_hi) || (te->count_lo != obj->count_lo)) { (void) reload_token_object(hContext, obj); obj->count_hi = te->count_hi; obj->count_lo = te->count_lo; } next = node->next; index++; } else { DL_NODE *new_node = NULL; OBJECT *new_obj = NULL; new_obj = (OBJECT *)malloc(sizeof (OBJECT)); (void) memset(new_obj, 0x0, sizeof (OBJECT)); (void) memcpy(new_obj->name, te->name, 8); (void) reload_token_object(hContext, new_obj); new_node = (DL_NODE *)malloc(sizeof (DL_NODE)); new_node->data = new_obj; new_node->next = node->next; node->next = new_node; new_node->prev = node; next = new_node->next; index++; } node = next; } if ((node == NULL) && (index < global_shm->num_publ_tok_obj)) { OBJECT *new_obj = NULL; unsigned int i; for (i = index; i < global_shm->num_publ_tok_obj; i++) { new_obj = (OBJECT *)malloc(sizeof (OBJECT)); (void) memset(new_obj, 0x0, sizeof (OBJECT)); te = &global_shm->publ_tok_objs[index]; (void) memcpy(new_obj->name, te->name, 8); (void) reload_token_object(hContext, new_obj); publ_token_obj_list = dlist_add_as_last( publ_token_obj_list, new_obj); } } else if ((node != NULL) && (index >= global_shm->num_publ_tok_obj)) { while (node) { obj = (OBJECT *)node->data; rc = object_mgr_find_in_map2(hContext, obj, &handle); if (rc == CKR_OK) { (void) object_mgr_remove_from_map(handle); } (void) object_free(obj); next = node->next; publ_token_obj_list = dlist_remove_node( publ_token_obj_list, node); node = next; } } return (CKR_OK); } static CK_RV object_mgr_update_priv_tok_obj_from_shm(TSS_HCONTEXT hContext) { DL_NODE * node = NULL; DL_NODE * next = NULL; TOK_OBJ_ENTRY * te = NULL; OBJECT * obj = NULL; CK_OBJECT_HANDLE handle; CK_ULONG index; int val; CK_RV rc; node = priv_token_obj_list; index = 0; if (! (global_login_state == CKS_RW_USER_FUNCTIONS || global_login_state == CKS_RO_USER_FUNCTIONS)) { return (CKR_OK); } while ((node != NULL) && (index < global_shm->num_priv_tok_obj)) { te = &global_shm->priv_tok_objs[index]; obj = (OBJECT *)node->data; val = memcmp(obj->name, te->name, 8); if (val < 0) { rc = object_mgr_find_in_map2(hContext, obj, &handle); if (rc == CKR_OK) { (void) object_mgr_remove_from_map(handle); } (void) object_free(obj); next = node->next; priv_token_obj_list = dlist_remove_node( priv_token_obj_list, node); } else if (val == 0) { if ((te->count_hi != obj->count_hi) || (te->count_lo != obj->count_lo)) { (void) reload_token_object(hContext, obj); obj->count_hi = te->count_hi; obj->count_lo = te->count_lo; } next = node->next; index++; } else { DL_NODE *new_node = NULL; OBJECT *new_obj = NULL; new_obj = (OBJECT *)malloc(sizeof (OBJECT)); (void) memset(new_obj, 0x0, sizeof (OBJECT)); (void) memcpy(new_obj->name, te->name, 8); (void) reload_token_object(hContext, new_obj); new_node = (DL_NODE *)malloc(sizeof (DL_NODE)); new_node->data = new_obj; new_node->next = node->next; node->next = new_node; new_node->prev = node; next = new_node->next; index++; } node = next; } if ((node == NULL) && (index < global_shm->num_priv_tok_obj)) { OBJECT *new_obj = NULL; unsigned int i; for (i = index; i < global_shm->num_priv_tok_obj; i++) { new_obj = (OBJECT *)malloc(sizeof (OBJECT)); (void) memset(new_obj, 0x0, sizeof (OBJECT)); te = &global_shm->priv_tok_objs[index]; (void) memcpy(new_obj->name, te->name, 8); (void) reload_token_object(hContext, new_obj); priv_token_obj_list = dlist_add_as_last( priv_token_obj_list, new_obj); } } else if ((node != NULL) && (index >= global_shm->num_priv_tok_obj)) { while (node) { obj = (OBJECT *)node->data; rc = object_mgr_find_in_map2(hContext, obj, &handle); if (rc == CKR_OK) { (void) object_mgr_remove_from_map(handle); } (void) object_free(obj); next = node->next; priv_token_obj_list = dlist_remove_node( priv_token_obj_list, node); node = next; } } return (CKR_OK); } static CK_RV object_mgr_update_from_shm(TSS_HCONTEXT hContext) { (void) object_mgr_update_publ_tok_obj_from_shm(hContext); (void) object_mgr_update_priv_tok_obj_from_shm(hContext); return (CKR_OK); } /*ARGSUSED*/ CK_BBOOL object_mgr_purge_map( SESSION *sess, SESS_OBJ_TYPE type) { DL_NODE *node = NULL; DL_NODE *next = NULL; if (pthread_rwlock_wrlock(&obj_list_rw_mutex)) { return (CKR_FUNCTION_FAILED); } node = object_map; while (node) { OBJECT_MAP *map = (OBJECT_MAP *)node->data; OBJECT *obj = (OBJECT *)map->ptr; next = node->next; if (type == PRIVATE) { if (object_is_private(obj)) { object_map = dlist_remove_node( object_map, node); free(map); } } if (type == PUBLIC) { if (object_is_public(obj)) { object_map = dlist_remove_node( object_map, node); free(map); } } node = next; } (void) pthread_rwlock_unlock(&obj_list_rw_mutex); return (TRUE); }