commit 84db3078dea9ffffbaeb76ad52e72dbdc8f6c8f1 Author: Joy Latten Date: Wed Oct 2 16:34:40 2013 -0500 CCA token was not importing rsa keypair correctly in v3. Signed-off-by: Joy Latten diff --git a/usr/lib/pkcs11/cca_stdll/obj_mgr.c b/usr/lib/pkcs11/cca_stdll/obj_mgr.c deleted file mode 100644 index 4c819e9..0000000 --- a/usr/lib/pkcs11/cca_stdll/obj_mgr.c +++ /dev/null @@ -1,2479 +0,0 @@ -/* - 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 - non-exclusive, worldwide, royalty-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 - non-exclusive, worldwide, royalty-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 non-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, NON-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 cross-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 cross-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 */ - - -// File: obj_mgr.c -// -// Object manager related functions -// - -#include -#include -#include -#include // for memcmp() et al -#include - -#include "pkcs11types.h" -#include "defs.h" -#include "cca_stdll.h" -#include "host_defs.h" -#include "h_extern.h" -#include "tok_spec_struct.h" - -#include "../api/apiproto.h" - -pthread_rwlock_t obj_list_rw_mutex = PTHREAD_RWLOCK_INITIALIZER; - -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_BBOOL locked = FALSE; - CK_RV rc; - unsigned long obj_handle; - - if (!sess || !pTemplate || !handle){ - OCK_LOG_ERR(ERR_FUNCTION_FAILED); - return CKR_FUNCTION_FAILED; - } - - rc = MY_LockMutex( &obj_list_mutex ); - if (rc != CKR_OK){ - OCK_LOG_ERR(ERR_MUTEX_LOCK); - return rc; - } - locked = TRUE; - - rc = object_create( pTemplate, ulCount, &o ); - if (rc != CKR_OK){ - OCK_LOG_ERR(ERR_OBJ_CREATE); - goto done; - } - - if (token_specific.t_object_add != NULL) { - rc = token_specific.t_object_add(o); - if (rc != CKR_OK) { - OCK_LOG_ERR(ERR_OBJ_CREATE); - goto done; - } - } - - // 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) { - OCK_LOG_ERR(ERR_USER_NOT_LOGGED_IN); - rc = CKR_USER_NOT_LOGGED_IN; - goto done; - } - - if (!sess_obj) { - OCK_LOG_ERR(ERR_SESSION_READ_ONLY); - rc = CKR_SESSION_READ_ONLY; - goto done; - } - } - - if (sess->session_info.state == CKS_RO_USER_FUNCTIONS) { - if (!sess_obj) { - OCK_LOG_ERR(ERR_SESSION_READ_ONLY); - rc = CKR_SESSION_READ_ONLY; - goto done; - } - } - - if (sess->session_info.state == CKS_RW_PUBLIC_SESSION) { - if (priv_obj) { - OCK_LOG_ERR(ERR_USER_NOT_LOGGED_IN); - rc = CKR_USER_NOT_LOGGED_IN; - goto done; - } - } - - if (sess->session_info.state == CKS_RW_SO_FUNCTIONS) { - if (priv_obj) { - OCK_LOG_ERR(ERR_USER_NOT_LOGGED_IN); - rc = CKR_USER_NOT_LOGGED_IN; - goto done; - } - } - - // okay, object is created and the session permissions look okay. - // add the object to the appropriate list and assign an object handle - // - - if (sess_obj) { - o->session = sess; - memset( o->name, 0x00, sizeof(CK_BYTE) * 8 ); - - if ((obj_handle = bt_node_add(&sess_obj_btree, o)) == 0) { - OCK_LOG_ERR(ERR_HOST_MEMORY); - rc = CKR_HOST_MEMORY; - goto done; - } - } - else { - CK_BYTE current[8]; - CK_BYTE next[8]; - - // we'll be modifying nv_token_data so we should protect this part with - // the 'pkcs_mutex' - // - rc = XProcLock(); - if (rc != CKR_OK){ - OCK_LOG_ERR(ERR_PROCESS_LOCK); - goto done; - } - else { - - // Determine if we have already reached our Max Token Objects - // - if (priv_obj) { - if (global_shm->num_priv_tok_obj >= MAX_TOK_OBJS) { - rc = CKR_HOST_MEMORY; - OCK_LOG_ERR(ERR_HOST_MEMORY); - XProcUnLock(); - goto done; - } - } - else { - if (global_shm->num_publ_tok_obj >= MAX_TOK_OBJS) { - rc = CKR_HOST_MEMORY; - OCK_LOG_ERR(ERR_HOST_MEMORY); - XProcUnLock(); - goto done; - } - } - - memcpy( current, &nv_token_data->next_token_object_name, 8 ); - - o->session = NULL; - memcpy( &o->name, current, 8 ); - - rc = compute_next_token_obj_name( current, next ); - if (rc != CKR_OK) { - // TODO: handle error, check if rc is a valid per spec - XProcUnLock(); - goto done; - } - memcpy( &nv_token_data->next_token_object_name, next, 8 ); - - rc = save_token_object( o ); - if (rc != CKR_OK) { - // TODO: handle error, check if rc is a valid per spec - XProcUnLock(); - goto done; - } - - // add the object identifier to the shared memory segment - // - object_mgr_add_to_shm( o ); - - XProcUnLock(); - - // save_token_data has to lock the mutex itself because it's used elsewhere - // - rc = save_token_data(); - if (rc != CKR_OK) { - // TODO: handle error, check if rc is a valid per spec - XProcUnLock(); - goto done; - } - - } - - // now, store the object in the appropriate btree - // - if (priv_obj) - obj_handle = bt_node_add(&priv_token_obj_btree, o); - else - obj_handle = bt_node_add(&publ_token_obj_btree, o); - - if (!obj_handle) { - OCK_LOG_ERR(ERR_HOST_MEMORY); - rc = CKR_HOST_MEMORY; - goto done; - } - } - - rc = object_mgr_add_to_map( sess, o, obj_handle, handle ); - if (rc != CKR_OK) { - // we need to remove the object from whatever btree we just added it to - if (sess_obj) { - // put the binary tree node which holds o on the free list, but pass NULL here, so that - // o (the binary tree node's value pointer) isn't touched. It is free'd below - bt_node_free(&sess_obj_btree, obj_handle, NULL); - } - else { - // we'll want to delete the token object file too! - // - delete_token_object( o ); - - if (priv_obj) { - // put the binary tree node which holds o on the free list, but pass NULL here, so that - // o (the binary tree node's value pointer) isn't touched. It is free'd below - bt_node_free(&priv_token_obj_btree, obj_handle, NULL); - } - else { - // put the binary tree node which holds o on the free list, but pass NULL here, so that - // o (the binary tree node's value pointer) isn't touched. It is free'd below - bt_node_free(&publ_token_obj_btree, obj_handle, NULL); - } - - rc = XProcLock(); - if (rc != CKR_OK){ - OCK_LOG_ERR(ERR_PROCESS_LOCK); - goto done; - } - object_mgr_del_from_shm( o ); - - XProcUnLock(); - } - } - - -done: - if (locked) - MY_UnlockMutex( &obj_list_mutex ); - - if ((rc != CKR_OK) && (o != NULL)) - object_free( o ); - - return rc; -} - - -// object_mgr_add_to_map() -// -CK_RV -object_mgr_add_to_map( SESSION * sess, - OBJECT * obj, - unsigned long obj_handle, - CK_OBJECT_HANDLE * map_handle ) -{ - OBJECT_MAP *map_node = NULL; - - if (!sess || !obj || !map_handle){ - OCK_LOG_ERR(ERR_FUNCTION_FAILED); - return CKR_FUNCTION_FAILED; - } - // - // this guy doesn't lock a mutex because it's calling routines should have - // already locked it - // - - map_node = (OBJECT_MAP *)malloc(sizeof(OBJECT_MAP)); - if (!map_node){ - OCK_LOG_ERR(ERR_HOST_MEMORY); - return CKR_HOST_MEMORY; - } - map_node->session = sess; - - if (obj->session != NULL) - map_node->is_session_obj = TRUE; - else - map_node->is_session_obj = FALSE; - - map_node->is_private = object_is_private( obj ); - - // add the new map entry to the list - if (pthread_rwlock_wrlock(&obj_list_rw_mutex)) { - free(map_node); - OCK_LOG_ERR(ERR_FUNCTION_FAILED); - return CKR_FUNCTION_FAILED; - } - - // map_node->obj_handle will store the index of the btree node in one of these lists: - // publ_token_obj_btree - for public token object - // priv_token_obj_btree - for private token objects - // sess_obj_btree - for session objects - // - // *map_handle, the application's CK_OBJECT_HANDLE, will then be the index of the btree node - // in the object_map_btree - // - map_node->obj_handle = obj_handle; - *map_handle = bt_node_add(&object_map_btree, map_node); - - pthread_rwlock_unlock(&obj_list_rw_mutex); - - if (*map_handle == 0) { - free(map_node); - OCK_LOG_ERR(ERR_HOST_MEMORY); - return CKR_HOST_MEMORY; - } - obj->map_handle = *map_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_BBOOL locked = FALSE; - CK_RV rc; - unsigned long obj_handle; - - if (!sess || !pTemplate || !new_handle){ - OCK_LOG_ERR(ERR_FUNCTION_FAILED); - return CKR_FUNCTION_FAILED; - } - - rc = MY_LockMutex( &obj_list_mutex ); - if (rc != CKR_OK){ - OCK_LOG_ERR(ERR_MUTEX_LOCK); - return rc; - } - locked = TRUE; - - rc = object_mgr_find_in_map1( old_handle, &old_obj ); - if (rc != CKR_OK){ - OCK_LOG_ERR(ERR_OBJMGR_FIND_MAP); - goto done; - } - rc = object_copy( pTemplate, ulCount, old_obj, &new_obj ); - if (rc != CKR_OK){ - OCK_LOG_ERR(ERR_OBJ_COPY); - goto done; - } - - // 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( new_obj ); - priv_obj = object_is_private( new_obj ); - - if (sess->session_info.state == CKS_RO_PUBLIC_SESSION) { - if (priv_obj) { - OCK_LOG_ERR(ERR_USER_NOT_LOGGED_IN); - rc = CKR_USER_NOT_LOGGED_IN; - goto done; - } - - if (!sess_obj) { - OCK_LOG_ERR(ERR_SESSION_READ_ONLY); - rc = CKR_SESSION_READ_ONLY; - goto done; - } - } - - if (sess->session_info.state == CKS_RO_USER_FUNCTIONS) { - if (!sess_obj) { - OCK_LOG_ERR(ERR_SESSION_READ_ONLY); - rc = CKR_SESSION_READ_ONLY; - goto done; - } - } - - if (sess->session_info.state == CKS_RW_PUBLIC_SESSION) { - if (priv_obj) { - OCK_LOG_ERR(ERR_USER_NOT_LOGGED_IN); - rc = CKR_USER_NOT_LOGGED_IN; - goto done; - } - } - - if (sess->session_info.state == CKS_RW_SO_FUNCTIONS) { - if (priv_obj) { - OCK_LOG_ERR(ERR_USER_NOT_LOGGED_IN); - rc = CKR_USER_NOT_LOGGED_IN; - goto done; - } - } - - // okay, object is created and the session permissions look okay. - // add the object to the appropriate list and assign an object handle - // - - if (sess_obj) { - new_obj->session = sess; - memset( &new_obj->name, 0x00, sizeof(CK_BYTE) * 8 ); - - if ((obj_handle = bt_node_add(&sess_obj_btree, new_obj)) == 0) { - OCK_LOG_ERR(ERR_HOST_MEMORY); - rc = CKR_HOST_MEMORY; - goto done; - } - } - else { - CK_BYTE current[8]; - CK_BYTE next[8]; - - // we'll be modifying nv_token_data so we should protect this part - // with 'pkcs_mutex' - // - rc = XProcLock(); - if (rc != CKR_OK){ - OCK_LOG_ERR(ERR_PROCESS_LOCK); - goto done; - } - else { - - // Determine if we have already reached our Max Token Objects - // - if (priv_obj) { - if (global_shm->num_priv_tok_obj >= MAX_TOK_OBJS) { - XProcUnLock(); - OCK_LOG_ERR(ERR_HOST_MEMORY); - rc = CKR_HOST_MEMORY; - goto done; - } - } - else { - if (global_shm->num_publ_tok_obj >= MAX_TOK_OBJS) { - XProcUnLock(); - OCK_LOG_ERR(ERR_HOST_MEMORY); - rc = CKR_HOST_MEMORY; - goto done; - } - } - memcpy( current, &nv_token_data->next_token_object_name, 8 ); - - new_obj->session = NULL; - memcpy( &new_obj->name, current, 8 ); - - compute_next_token_obj_name( current, next ); - memcpy( &nv_token_data->next_token_object_name, next, 8 ); - - save_token_object( new_obj ); - - // add the object identifier to the shared memory segment - // - object_mgr_add_to_shm( new_obj ); - - XProcUnLock(); - - save_token_data(); - } - - // now, store the object in the token object btree - // - if (priv_obj) - obj_handle = bt_node_add(&priv_token_obj_btree, new_obj); - else - obj_handle = bt_node_add(&publ_token_obj_btree, new_obj); - - if (!obj_handle) { - OCK_LOG_ERR(ERR_HOST_MEMORY); - rc = CKR_HOST_MEMORY; - goto done; - } - } - - rc = object_mgr_add_to_map( sess, new_obj, obj_handle, new_handle ); - if (rc != CKR_OK) { - OCK_LOG_ERR(ERR_OBJMGR_MAP_ADD); - - // this is messy but we need to remove the object from whatever - // list we just added it to - // - if (sess_obj) { - // put the binary tree node which holds new_obj on the free list, but pass NULL here, so - // that new_obj (the binary tree node's value pointer) isn't touched. It is free'd below - bt_node_free(&sess_obj_btree, obj_handle, NULL); - } - else { - // FIXME - need to destroy the token object file too - // - delete_token_object( new_obj ); - - if (priv_obj) { - // put the binary tree node which holds new_obj on the free list, but pass NULL here, - // so that new_obj (the binary tree node's value pointer) isn't touched. It is free'd - // below - bt_node_free(&priv_token_obj_btree, obj_handle, NULL); - } - else { - // put the binary tree node which holds new_obj on the free list, but pass NULL here, - // so that new_obj (the binary tree node's value pointer) isn't touched. It is free'd - // below - bt_node_free(&publ_token_obj_btree, obj_handle, NULL); - } - - rc = XProcLock(); - if (rc != CKR_OK){ - OCK_LOG_ERR(ERR_PROCESS_LOCK); - goto done; - } - object_mgr_del_from_shm( new_obj ); - - XProcUnLock(); - } - } - -done: - if (locked) - MY_UnlockMutex( &obj_list_mutex ); - - if ((rc != CKR_OK) && (new_obj != NULL)) - 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){ - OCK_LOG_ERR(ERR_FUNCTION_FAILED); - return CKR_FUNCTION_FAILED; - } - if (!pTemplate && (ulCount != 0)){ - OCK_LOG_ERR(ERR_FUNCTION_FAILED); - return CKR_FUNCTION_FAILED; - } - // - // we don't need to lock mutex for this routine - // - - rc = object_create_skel( pTemplate, ulCount, - mode, - obj_type, sub_class, - &o ); - if (rc != CKR_OK){ - OCK_LOG_ERR(ERR_OBJMGR_CREATE_SKEL); - 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) { - object_free( o ); - OCK_LOG_ERR(ERR_USER_NOT_LOGGED_IN); - return CKR_USER_NOT_LOGGED_IN; - } - - if (!sess_obj) { - object_free( o ); - OCK_LOG_ERR(ERR_SESSION_READ_ONLY); - return CKR_SESSION_READ_ONLY; - } - } - - if (sess->session_info.state == CKS_RO_USER_FUNCTIONS) { - if (!sess_obj) { - object_free( o ); - OCK_LOG_ERR(ERR_SESSION_READ_ONLY); - return CKR_SESSION_READ_ONLY; - } - } - - if (sess->session_info.state == CKS_RW_PUBLIC_SESSION) { - if (priv_obj) { - object_free( o ); - OCK_LOG_ERR(ERR_USER_NOT_LOGGED_IN); - return CKR_USER_NOT_LOGGED_IN; - } - } - - if (sess->session_info.state == CKS_RW_SO_FUNCTIONS) { - if (priv_obj) { - object_free( o ); - OCK_LOG_ERR(ERR_USER_NOT_LOGGED_IN); - 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_BBOOL locked = FALSE; - CK_RV rc; - unsigned long obj_handle; - - if (!sess || !obj || !handle){ - OCK_LOG_ERR(ERR_FUNCTION_FAILED); - return CKR_FUNCTION_FAILED; - } - rc = MY_LockMutex( &obj_list_mutex ); - if (rc != CKR_OK){ - OCK_LOG_ERR(ERR_MUTEX_LOCK); - return rc; - } - locked = TRUE; - - sess_obj = object_is_session_object( obj ); - priv_obj = object_is_private( obj ); - - if (sess_obj) { - obj->session = sess; - memset( obj->name, 0x0, sizeof(CK_BYTE) * 8 ); - - if ((obj_handle = bt_node_add(&sess_obj_btree, obj)) == 0) { - OCK_LOG_ERR(ERR_HOST_MEMORY); - rc = CKR_HOST_MEMORY; - goto done; - } - } - else { - CK_BYTE current[8]; - CK_BYTE next[8]; - - // we'll be modifying nv_token_data so we should protect this part - // with 'pkcs_mutex' - // - rc = XProcLock(); - if (rc != CKR_OK){ - OCK_LOG_ERR(ERR_PROCESS_LOCK); - goto done; - } - else { - - // Determine if we have already reached our Max Token Objects - // - if (priv_obj) { - if (global_shm->num_priv_tok_obj >= MAX_TOK_OBJS) { - XProcUnLock(); - OCK_LOG_ERR(ERR_HOST_MEMORY); - rc = CKR_HOST_MEMORY; - goto done; - } - } - else { - if (global_shm->num_publ_tok_obj >= MAX_TOK_OBJS) { - XProcUnLock(); - OCK_LOG_ERR(ERR_HOST_MEMORY); - rc = CKR_HOST_MEMORY; - goto done; - } - } - memcpy( current, &nv_token_data->next_token_object_name, 8 ); - - obj->session = NULL; - memcpy( &obj->name, current, 8 ); - - compute_next_token_obj_name( current, next ); - memcpy( &nv_token_data->next_token_object_name, next, 8 ); - - save_token_object( obj ); - - // add the object identifier to the shared memory segment - // - object_mgr_add_to_shm( obj ); - - XProcUnLock(); - - save_token_data(); - } - - // now, store the object in the token object btree - // - if (priv_obj) - obj_handle = bt_node_add(&priv_token_obj_btree, obj); - else - obj_handle = bt_node_add(&publ_token_obj_btree, obj); - - if (!obj_handle) { - OCK_LOG_ERR(ERR_HOST_MEMORY); - rc = CKR_HOST_MEMORY; - goto done; - } - } - - rc = object_mgr_add_to_map( sess, obj, obj_handle, handle ); - if (rc != CKR_OK) { - OCK_LOG_ERR(ERR_OBJMGR_MAP_ADD); - // this is messy but we need to remove the object from whatever - // list we just added it to - // - if (sess_obj) { - // put the binary tree node which holds obj on the free list, but pass NULL here, so - // that obj (the binary tree node's value pointer) isn't touched. It is free'd below - bt_node_free(&sess_obj_btree, obj_handle, NULL); - } - else { - // FIXME - need to destroy the token object file too - // - delete_token_object( obj ); - - if (priv_obj) { - // put the binary tree node which holds obj on the free list, but pass NULL here, - // so that obj (the binary tree node's value pointer) isn't touched. It is free'd - // below - bt_node_free(&priv_token_obj_btree, obj_handle, NULL); - } - else { - // put the binary tree node which holds obj on the free list, but pass NULL here, - // so that obj (the binary tree node's value pointer) isn't touched. It is free'd - // below - bt_node_free(&publ_token_obj_btree, obj_handle, NULL); - } - - rc = XProcLock(); - if (rc != CKR_OK){ - OCK_LOG_ERR(ERR_PROCESS_LOCK); - goto done; - } - object_mgr_del_from_shm( obj ); - - XProcUnLock(); - } - } - -done: - if (locked) - MY_UnlockMutex( &obj_list_mutex ); - - return rc; -} - -/* destroy_object_cb - * - * Callback used to delete an object from the object map btree and whichever other btree its - * in (based on its type) - */ -void -destroy_object_cb(void *node) -{ - OBJECT_MAP *map = (OBJECT_MAP *)node; - OBJECT *o; - - if (map->is_session_obj) - bt_node_free(&sess_obj_btree, map->obj_handle, object_free); - else { - if (map->is_private) - o = bt_get_node_value(&priv_token_obj_btree, map->obj_handle); - else - o = bt_get_node_value(&publ_token_obj_btree, map->obj_handle); - - if (!o) - return; - - delete_token_object(o); - - /* Use the same calling convention as the old code, if XProcLock fails, don't - * delete from shm and don't free the object in its other btree */ - if (XProcLock()) { - OCK_LOG_ERR(ERR_PROCESS_LOCK); - goto done; - } - DUMP_SHM("before"); - object_mgr_del_from_shm(o); - DUMP_SHM("after"); - - XProcUnLock(); - - if (map->is_private) - bt_node_free(&priv_token_obj_btree, map->obj_handle, object_free); - else - bt_node_free(&publ_token_obj_btree, map->obj_handle, object_free); - } -done: - free(map); -} - -// XXX Why does this function take @sess as an argument? -// -CK_RV -object_mgr_destroy_object( SESSION * sess, - CK_OBJECT_HANDLE handle ) -{ - CK_BBOOL locked = FALSE; - CK_RV rc; - - - if (!sess){ - OCK_LOG_ERR(ERR_FUNCTION_FAILED); - return CKR_FUNCTION_FAILED; - } - rc = MY_LockMutex( &obj_list_mutex ); - if (rc != CKR_OK){ - OCK_LOG_ERR(ERR_MUTEX_LOCK); - goto done; - } - locked = TRUE; - if (pthread_rwlock_wrlock(&obj_list_rw_mutex)) { - OCK_LOG_ERR(ERR_FUNCTION_FAILED); - rc = CKR_FUNCTION_FAILED; - goto done; // FIXME: Proper error messages - } - - if (!bt_node_free(&object_map_btree, handle, destroy_object_cb)) { - OCK_LOG_ERR(ERR_OBJECT_HANDLE_INVALID); - rc = CKR_OBJECT_HANDLE_INVALID; - } - - pthread_rwlock_unlock(&obj_list_rw_mutex); -done: - if (locked) - MY_UnlockMutex( &obj_list_mutex ); - - return rc; -} - -/* delete_token_obj_cb - * - * Callback to delete an object if its a token object - */ -void -delete_token_obj_cb(void *node, unsigned long map_handle, void *p3) -{ - OBJECT_MAP *map = (OBJECT_MAP *)node; - OBJECT *o; - - if (!(map->is_session_obj)) { - if (map->is_private) - o = bt_get_node_value(&priv_token_obj_btree, map->obj_handle); - else - o = bt_get_node_value(&publ_token_obj_btree, map->obj_handle); - - if (!o) - goto done; - - delete_token_object(o); - - /* Use the same calling convention as the old code, if - * XProcLock fails, don't delete from shm and don't free - * the object in its other btree - */ - if (XProcLock()) { - OCK_LOG_ERR(ERR_PROCESS_LOCK); - goto done; - } - - object_mgr_del_from_shm(o); - - XProcUnLock(); - - if (map->is_private) - bt_node_free(&priv_token_obj_btree, map->obj_handle, object_free); - else - bt_node_free(&publ_token_obj_btree, map->obj_handle, object_free); - } -done: - /* delete @node from this btree */ - bt_node_free(&object_map_btree, map_handle, free); -} - -// this routine will destroy all token objects in the system -// -CK_RV -object_mgr_destroy_token_objects( void ) -{ - CK_BBOOL locked1 = FALSE, locked2 = FALSE; - CK_RV rc; - - rc = MY_LockMutex( &obj_list_mutex ); - if (rc != CKR_OK){ - OCK_LOG_ERR(ERR_MUTEX_LOCK); - goto done; - } - else - locked1 = TRUE; - bt_for_each_node(&object_map_btree, delete_token_obj_cb, NULL); - - // now we want to purge the token object list in shared memory - // - rc = XProcLock(); - if (rc == CKR_OK) { - locked2 = TRUE; - - global_shm->num_priv_tok_obj = 0; - global_shm->num_publ_tok_obj = 0; - - memset( &global_shm->publ_tok_objs, 0x0, MAX_TOK_OBJS * sizeof(TOK_OBJ_ENTRY) ); - memset( &global_shm->priv_tok_objs, 0x0, MAX_TOK_OBJS * sizeof(TOK_OBJ_ENTRY) ); - } - else - OCK_LOG_ERR(ERR_PROCESS_LOCK); -done: - if (locked1 == TRUE) MY_UnlockMutex( &obj_list_mutex ); -/* if (locked2 == TRUE) XProcUnLock(); */ - if (locked2 == TRUE) { - XProcUnLock(); - } - - return rc; -} - - -// object_mgr_find_in_map_nocache() -// -// 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_MAP * map = NULL; - OBJECT * obj = NULL; - CK_RV rc = CKR_OK; - - - if (!ptr){ - OCK_LOG_ERR(ERR_FUNCTION_FAILED); - return CKR_FUNCTION_FAILED; - } - - if (!handle) { - OCK_LOG_ERR(ERR_OBJECT_HANDLE_INVALID); - return CKR_OBJECT_HANDLE_INVALID; - } - - // - // no mutex here. the calling function should have locked the mutex - // - - if (pthread_rwlock_rdlock(&obj_list_rw_mutex)) { - OCK_LOG_ERR(ERR_FUNCTION_FAILED); - return CKR_FUNCTION_FAILED; - } - - map = bt_get_node_value(&object_map_btree, handle); - if (!map) { - OCK_LOG_ERR(ERR_OBJECT_HANDLE_INVALID); - rc = CKR_OBJECT_HANDLE_INVALID; - goto done; - } - - if (map->is_session_obj) - obj = bt_get_node_value(&sess_obj_btree, map->obj_handle); - else if (map->is_private) - obj = bt_get_node_value(&priv_token_obj_btree, map->obj_handle); - else - obj = bt_get_node_value(&publ_token_obj_btree, map->obj_handle); - - if (!obj) { - OCK_LOG_ERR(ERR_OBJECT_HANDLE_INVALID); - rc = CKR_OBJECT_HANDLE_INVALID; - goto done; - } - - *ptr = obj; -done: - pthread_rwlock_unlock(&obj_list_rw_mutex); - - return rc; -} - -// object_mgr_find_in_map1() -// -// Locates the specified object in the map -// -CK_RV -object_mgr_find_in_map1( CK_OBJECT_HANDLE handle, - OBJECT ** ptr ) -{ - OBJECT_MAP * map = NULL; - OBJECT * obj = NULL; - CK_RV rc = CKR_OK; - - - if (!ptr){ - OCK_LOG_ERR(ERR_FUNCTION_FAILED); - return CKR_FUNCTION_FAILED; - } - if (pthread_rwlock_rdlock(&obj_list_rw_mutex)) { - OCK_LOG_ERR(ERR_FUNCTION_FAILED); - return CKR_FUNCTION_FAILED; - } - - map = bt_get_node_value(&object_map_btree, handle); - if (!map) { - OCK_LOG_ERR(ERR_OBJECT_HANDLE_INVALID); - rc = CKR_OBJECT_HANDLE_INVALID; - goto done; - } - - if (map->is_session_obj) - obj = bt_get_node_value(&sess_obj_btree, map->obj_handle); - else if (map->is_private) - obj = bt_get_node_value(&priv_token_obj_btree, map->obj_handle); - else - obj = bt_get_node_value(&publ_token_obj_btree, map->obj_handle); - - if (!obj) { - OCK_LOG_ERR(ERR_OBJECT_HANDLE_INVALID); - rc = CKR_OBJECT_HANDLE_INVALID; - goto done; - } - -// SAB XXX Fix me.. need to make it more efficient than just looking for the object to be changed -// set a global flag that contains the ref count to all objects.. if the shm ref count changes, then we update the object -// if not - - XProcLock(); - object_mgr_check_shm( obj ); - XProcUnLock(); - - *ptr = obj; -done: - pthread_rwlock_unlock(&obj_list_rw_mutex); - - return rc; -} - -void -find_obj_cb(void *node, unsigned long map_handle, void *p3) -{ - OBJECT_MAP *map = (OBJECT_MAP *)node; - OBJECT *obj; - struct find_args *fa = (struct find_args *)p3; - - if (fa->done) - return; - - if (map->is_session_obj) - obj = bt_get_node_value(&sess_obj_btree, map->obj_handle); - else if (map->is_private) - obj = bt_get_node_value(&priv_token_obj_btree, map->obj_handle); - else - obj = bt_get_node_value(&publ_token_obj_btree, map->obj_handle); - - if (!obj) - return; - - /* if this object is the one we're looking for (matches p3->obj), return - * its map_handle in p3->map_handle */ - if (obj == fa->obj) { - fa->map_handle = map_handle; - fa->done = TRUE; - } -} - -// object_mgr_find_in_map2() -// -CK_RV -object_mgr_find_in_map2( OBJECT * obj, - CK_OBJECT_HANDLE * handle ) -{ - struct find_args fa; - - if (!obj || !handle){ - OCK_LOG_ERR(ERR_FUNCTION_FAILED); - return CKR_FUNCTION_FAILED; - } - // - // no mutex here. the calling function should have locked the mutex - // - - if (pthread_rwlock_rdlock(&obj_list_rw_mutex)) { - OCK_LOG_ERR(ERR_FUNCTION_FAILED); - return CKR_FUNCTION_FAILED; - } - - fa.done = FALSE; - fa.obj = obj; - fa.map_handle = 0; - - // pass the fa structure with the values to operate on in the find_obj_cb function - bt_for_each_node(&object_map_btree, find_obj_cb, &fa); - - pthread_rwlock_unlock(&obj_list_rw_mutex); - - if (fa.done == FALSE || fa.map_handle == 0) { - return CKR_OBJECT_HANDLE_INVALID; - } - - *handle = fa.map_handle; - - XProcLock(); - object_mgr_check_shm( obj ); - XProcUnLock(); - - return CKR_OK; -} - -void -find_build_list_cb(void *node, unsigned long obj_handle, void *p3) -{ - OBJECT *obj = (OBJECT *)node; - struct find_build_list_args *fa = (struct find_build_list_args *)p3; - CK_OBJECT_HANDLE map_handle; - CK_ATTRIBUTE *attr; - CK_BBOOL match = FALSE; - CK_RV rc; - - if ((object_is_private(obj) == FALSE) || (fa->public_only == FALSE)) { - // if the user doesn't specify any template attributes then we return - // all objects - // - if (fa->pTemplate == NULL || fa->ulCount == 0) - match = TRUE; - else - match = template_compare( fa->pTemplate, fa->ulCount, obj->template ); - } - - // if we have a match, find the object in the map (add it if necessary) - // then add the object to the list of found objects // - if (match) { - rc = object_mgr_find_in_map2( obj, &map_handle ); - if (rc != CKR_OK) { - //OCK_LOG_ERR(ERR_OBJMGR_FIND_MAP); - rc = object_mgr_add_to_map( fa->sess, obj, obj_handle, &map_handle ); - if (rc != CKR_OK){ - OCK_LOG_ERR(ERR_FUNCTION_FAILED); - return; - } - } - - // If hw_feature is false here, we need to filter out all objects - // that have the CKO_HW_FEATURE attribute set. - KEY - if ((fa->hw_feature == FALSE) && - (template_attribute_find(obj->template, CKA_CLASS, &attr) == TRUE)) { - //axelrh: prevent segfault if pValue set to NULL (bad parse) - if (attr->pValue == NULL) { - OCK_LOG_ERR(ERR_GENERAL_ERROR); - return; - } - if (*(CK_OBJECT_CLASS *)attr->pValue == CKO_HW_FEATURE) - return; - } - - /* Don't find objects that have been created with the CKA_HIDDEN - * attribute set */ - if ((fa->hidden_object == FALSE) && - (template_attribute_find(obj->template, CKA_HIDDEN, &attr) == TRUE)) { - if (*(CK_BBOOL *)attr->pValue == TRUE) - return; - } - - fa->sess->find_list[ fa->sess->find_count ] = map_handle; - fa->sess->find_count++; - - if (fa->sess->find_count >= fa->sess->find_len) { - fa->sess->find_len += 15; - fa->sess->find_list = - (CK_OBJECT_HANDLE *)realloc(fa->sess->find_list, - fa->sess->find_len * sizeof(CK_OBJECT_HANDLE)); - if (!fa->sess->find_list) { - OCK_LOG_ERR(ERR_HOST_MEMORY); - return; - } - } - } -} - -CK_RV -object_mgr_find_init( SESSION * sess, - CK_ATTRIBUTE * pTemplate, - CK_ULONG ulCount ) -{ - struct find_build_list_args fa; - CK_ULONG i; - // it is possible the pTemplate == NULL - // - - if (!sess){ - OCK_LOG_ERR(ERR_FUNCTION_FAILED); - return CKR_FUNCTION_FAILED; - } - if (sess->find_active != FALSE){ - return CKR_OPERATION_ACTIVE; - OCK_LOG_ERR(ERR_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) { - 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){ - OCK_LOG_ERR(ERR_HOST_MEMORY); - return CKR_HOST_MEMORY; - } - else { - 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 - MY_LockMutex(&obj_list_mutex); - XProcLock(); - object_mgr_update_from_shm(); - XProcUnLock(); - - fa.hw_feature = FALSE; - fa.hidden_object = FALSE; - fa.sess = sess; - fa.pTemplate = pTemplate; - fa.ulCount = ulCount; - - // which objects can be returned: - // - // Public Session: public session objects, public token objects - // User Session: all session objects, all token objects - // SO session: public session objects, public token objects - // - // 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) { - fa.hw_feature = TRUE; - break; - } - } - - /* only find CKA_HIDDEN objects if its specified in the template. */ - if (pTemplate[i].type == CKA_HIDDEN) { - if (*(CK_BBOOL *)pTemplate[i].pValue == TRUE) { - fa.hidden_object = TRUE; - break; - } - } - } - - switch (sess->session_info.state) { - case CKS_RO_PUBLIC_SESSION: - case CKS_RW_PUBLIC_SESSION: - case CKS_RW_SO_FUNCTIONS: - fa.public_only = TRUE; - - bt_for_each_node(&publ_token_obj_btree, find_build_list_cb, &fa); - bt_for_each_node(&sess_obj_btree, find_build_list_cb, &fa); - break; - - case CKS_RO_USER_FUNCTIONS: - case CKS_RW_USER_FUNCTIONS: - fa.public_only = FALSE; - - bt_for_each_node(&priv_token_obj_btree, find_build_list_cb, &fa); - bt_for_each_node(&publ_token_obj_btree, find_build_list_cb, &fa); - bt_for_each_node(&sess_obj_btree, find_build_list_cb, &fa); - break; - } - - MY_UnlockMutex(&obj_list_mutex); - - sess->find_active = TRUE; - - return CKR_OK; -} - -// -// -CK_RV -object_mgr_find_final( SESSION *sess ) -{ - if (!sess){ - OCK_LOG_ERR(ERR_FUNCTION_FAILED); - return CKR_FUNCTION_FAILED; - } - if (sess->find_active == FALSE){ - OCK_LOG_ERR(ERR_OPERATION_NOT_INITIALIZED); - 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_BBOOL locked = FALSE; - CK_RV rc; - - if (!pTemplate){ - OCK_LOG_ERR(ERR_FUNCTION_FAILED); - return CKR_FUNCTION_FAILED; - } - rc = MY_LockMutex( &obj_list_mutex ); - if (rc != CKR_OK){ - OCK_LOG_ERR(ERR_MUTEX_LOCK); - return rc; - } - locked = TRUE; - - rc = object_mgr_find_in_map1( handle, &obj ); - if (rc != CKR_OK){ - OCK_LOG_ERR(ERR_OBJMGR_FIND_MAP); - 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) - { - OCK_LOG_ERR(ERR_USER_NOT_LOGGED_IN); - rc = CKR_USER_NOT_LOGGED_IN; - goto done; - } - } - - rc = object_get_attribute_values( obj, pTemplate, ulCount ); - if (rc != CKR_OK) - OCK_LOG_ERR(ERR_OBJ_GETATTR_VALUES); -done: - if (locked) - MY_UnlockMutex( &obj_list_mutex ); - - return rc; -} - - -// -// -CK_RV -object_mgr_get_object_size( CK_OBJECT_HANDLE handle, - CK_ULONG * size ) -{ - OBJECT * obj; - CK_RV rc; - - rc = MY_LockMutex( &obj_list_mutex ); - if (rc != CKR_OK){ - OCK_LOG_ERR(ERR_MUTEX_LOCK); - return rc; - } - rc = object_mgr_find_in_map1( handle, &obj ); - if (rc != CKR_OK) { - OCK_LOG_ERR(ERR_OBJECT_HANDLE_INVALID); - rc = CKR_OBJECT_HANDLE_INVALID; - goto done; - } - - *size = object_get_size( obj ); - -done: - MY_UnlockMutex( &obj_list_mutex ); - return rc; -} - -void -purge_session_obj_cb(void *node, unsigned long obj_handle, void *p3) -{ - OBJECT *obj = (OBJECT *)node; - struct purge_args *pa = (struct purge_args *)p3; - CK_BBOOL del = FALSE; - - if (obj->session == pa->sess) { - if (pa->type == PRIVATE) { - if (object_is_private(obj)) - del = TRUE; - } - else if (pa->type == PUBLIC) { - if (object_is_public(obj)) - del = TRUE; - } - else if (pa->type == ALL) { - del = TRUE; - } - - if (del == TRUE) { - if (obj->map_handle) - bt_node_free(&object_map_btree, obj->map_handle, free); - - bt_node_free(&sess_obj_btree, obj_handle, object_free); - } - } -} - -// 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 ) -{ - struct purge_args pa = { sess, type }; - CK_RV rc; - - if (!sess) - return FALSE; - - rc = MY_LockMutex( &obj_list_mutex ); - if (rc != CKR_OK){ - OCK_LOG_ERR(ERR_MUTEX_LOCK); - return FALSE; - } - - bt_for_each_node(&sess_obj_btree, purge_session_obj_cb, &pa); - - MY_UnlockMutex( &obj_list_mutex ); - - return TRUE; -} - -/* purge_token_obj_cb - * - * @p3 is the btree we're purging from - */ -void -purge_token_obj_cb(void *node, unsigned long obj_handle, void *p3) -{ - OBJECT *obj = (OBJECT *)node; - struct btree *t = (struct btree *)p3; - - if (obj->map_handle) - bt_node_free(&object_map_btree, obj->map_handle, free); - - bt_node_free(t, obj_handle, object_free); -} - -// 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( ) -{ - CK_RV rc; - - rc = MY_LockMutex( &obj_list_mutex ); - if (rc != CKR_OK){ - OCK_LOG_ERR(ERR_MUTEX_LOCK); - return FALSE; - } - - bt_for_each_node(&priv_token_obj_btree, purge_token_obj_cb, &priv_token_obj_btree); - bt_for_each_node(&publ_token_obj_btree, purge_token_obj_cb, &publ_token_obj_btree); - - MY_UnlockMutex( &obj_list_mutex ); - - return TRUE; -} - - -CK_BBOOL -object_mgr_purge_private_token_objects( void ) -{ - CK_RV rc; - - rc = MY_LockMutex( &obj_list_mutex ); - if (rc != CKR_OK){ - OCK_LOG_ERR(ERR_MUTEX_LOCK); - return FALSE; - } - - bt_for_each_node(&priv_token_obj_btree, purge_token_obj_cb, &priv_token_obj_btree); - - MY_UnlockMutex( &obj_list_mutex ); - - return TRUE; -} - -// -// -CK_RV -object_mgr_restore_obj( CK_BYTE *data, OBJECT *oldObj ) -{ - return object_mgr_restore_obj_withSize(data, oldObj, -1); -} - -// -//Modified verrsion of object_mgr_restore_obj to bounds check -//If data_size==-1, won't check bounds -CK_RV -object_mgr_restore_obj_withSize( CK_BYTE *data, OBJECT *oldObj, int data_size ) -{ - OBJECT * obj = NULL; - CK_BBOOL priv; - CK_RV rc; - - if (!data){ - OCK_LOG_ERR(ERR_FUNCTION_FAILED); - return CKR_FUNCTION_FAILED; - } - // The calling stack MUST have the mutex - // to many grab it now. - - if (oldObj != NULL) { - obj = oldObj; - rc = object_restore_withSize( data, &obj, TRUE, data_size ); - } - else { - rc = object_restore_withSize( data, &obj, FALSE, data_size ); - if (rc == CKR_OK) { - priv = object_is_private( obj ); - - if (priv) { - if (!bt_node_add(&priv_token_obj_btree, obj)) { - OCK_LOG_ERR(ERR_HOST_MEMORY); - return CKR_HOST_MEMORY; - } - } else { - if (!bt_node_add(&publ_token_obj_btree, obj)) { - OCK_LOG_ERR(ERR_HOST_MEMORY); - return CKR_HOST_MEMORY; - } - } - - XProcLock(); - - if (priv) { - if (global_shm->priv_loaded == FALSE){ - if (global_shm->num_priv_tok_obj < MAX_TOK_OBJS) - object_mgr_add_to_shm( obj ); - else{ - OCK_LOG_ERR(ERR_HOST_MEMORY); - rc = CKR_HOST_MEMORY; - } - } - } else { - if (global_shm->publ_loaded == FALSE){ - if (global_shm->num_publ_tok_obj < MAX_TOK_OBJS) - object_mgr_add_to_shm( obj ); - else{ - OCK_LOG_ERR(ERR_HOST_MEMORY); - rc = CKR_HOST_MEMORY; - } - } - } - - XProcUnLock(); - } else { - OCK_LOG_ERR(ERR_OBJ_RESTORE_DATA); - } - } - - 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){ - OCK_LOG_ERR(ERR_FUNCTION_FAILED); - return CKR_FUNCTION_FAILED; - } - rc = MY_LockMutex( &obj_list_mutex ); - if (rc != CKR_OK){ - OCK_LOG_ERR(ERR_MUTEX_LOCK); - return rc; - } - - rc = object_mgr_find_in_map1( handle, &obj ); - - MY_UnlockMutex( &obj_list_mutex ); - - if (rc != CKR_OK) { - OCK_LOG_ERR(ERR_OBJMGR_FIND_MAP); - return CKR_OBJECT_HANDLE_INVALID; - } - - // determine whether the session is allowed to modify the object - // - modifiable = object_is_modifiable( obj ); - sess_obj = object_is_session_object( obj ); - priv_obj = object_is_private( obj ); - - // if object is not modifiable, it doesn't matter what kind of session - // is issuing the request... - // - if (!modifiable){ - OCK_LOG_ERR(ERR_ATTRIBUTE_READ_ONLY); - return CKR_ATTRIBUTE_READ_ONLY; - } - if (sess->session_info.state == CKS_RO_PUBLIC_SESSION) { - if (priv_obj){ - OCK_LOG_ERR(ERR_USER_NOT_LOGGED_IN); - return CKR_USER_NOT_LOGGED_IN; - } - if (!sess_obj){ - OCK_LOG_ERR(ERR_SESSION_READ_ONLY); - return CKR_SESSION_READ_ONLY; - } - } - - if (sess->session_info.state == CKS_RO_USER_FUNCTIONS) { - if (!sess_obj){ - OCK_LOG_ERR(ERR_SESSION_READ_ONLY); - return CKR_SESSION_READ_ONLY; - } - } - - if (sess->session_info.state == CKS_RW_PUBLIC_SESSION) { - if (priv_obj){ - OCK_LOG_ERR(ERR_USER_NOT_LOGGED_IN); - return CKR_USER_NOT_LOGGED_IN; - } - } - - if (sess->session_info.state == CKS_RW_SO_FUNCTIONS) { - if (priv_obj){ - OCK_LOG_ERR(ERR_USER_NOT_LOGGED_IN); - return CKR_USER_NOT_LOGGED_IN; - } - } - - - rc = object_set_attribute_values( obj, pTemplate, ulCount ); - if (rc != CKR_OK){ - OCK_LOG_ERR(ERR_OBJ_SETATTR_VALUES); - return rc; - } - // okay. the object has been updated. if it's a session object, - // we're finished. if it's a token object, we need to update - // non-volatile storage. - // - if (!sess_obj) { - TOK_OBJ_ENTRY *entry = NULL; - CK_ULONG index; - - // I still think there's a race condition here if two processes are - // updating the same token object at the same time. I don't know how - // to solve this short of assigning each token object it's own mutex... - // - obj->count_lo++; - if (obj->count_lo == 0) - obj->count_hi++; - - save_token_object( obj ); - - rc = XProcLock(); - if (rc != CKR_OK){ - OCK_LOG_ERR(ERR_PROCESS_LOCK); - 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) { - OCK_LOG_ERR(ERR_OBJMGR_SEARCH); - XProcUnLock(); - 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) { - OCK_LOG_ERR(ERR_OBJMGR_SEARCH); - XProcUnLock(); - return rc; - } - - entry = &global_shm->publ_tok_objs[index]; - } - - entry->count_lo = obj->count_lo; - entry->count_hi = obj->count_hi; - - XProcUnLock(); - } - - return rc; -} - - -// -// -void -object_mgr_add_to_shm( OBJECT *obj ) -{ - // TODO: Can't this function fail? - TOK_OBJ_ENTRY * entry = NULL; - CK_BBOOL priv; - - // the calling routine is responsible for locking the global_shm mutex - // - - 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; - memcpy( entry->name, obj->name, 8 ); - - if (priv) { - global_shm->num_priv_tok_obj++; - object_mgr_sort_priv_shm(); - } - else { - global_shm->num_publ_tok_obj++; - object_mgr_sort_publ_shm(); - } - - return; -} - - -// -// -CK_RV -object_mgr_del_from_shm( OBJECT *obj ) -{ - CK_ULONG index, count; - CK_BBOOL priv; - CK_RV rc; - - - // the calling routine is responsible for locking the global_shm mutex - // - - 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){ - OCK_LOG_ERR(ERR_FUNCTION_FAILED); - return CKR_FUNCTION_FAILED; - } - // Since the number of objects starts at 1 and index starts at zero, we - // decrement before we get count. This eliminates the need to perform - // this operation later as well as decrementing the number of objects. - // (i.e. If we have 10 objects, num will be 10 but the last index is 9. - // If we want to delete the last object we need to subtract 9 from 9 not - // 10 from 9.) - // - 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) { // If we are not deleting the last element in the list - // Move up count number of elements effectively deleting the index - // NB: memmove is required since the copied regions may overlap - memmove((char *)&global_shm->priv_tok_objs[index], - (char *)&global_shm->priv_tok_objs[index+1], - sizeof(TOK_OBJ_ENTRY) * count ); - // We need to zero out the last entry... Since the memcopy - // does not zero it out... - memset((char *)&global_shm->priv_tok_objs[global_shm->num_priv_tok_obj+1], 0, - sizeof(TOK_OBJ_ENTRY)); - } - else { // We are deleting the last element which is in num_priv_tok_obj - 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){ - OCK_LOG_ERR(ERR_FUNCTION_FAILED); - 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) { - // NB: memmove is required since the copied regions may overlap - memmove((char *)&global_shm->publ_tok_objs[index], - (char *)&global_shm->publ_tok_objs[index+1], - sizeof(TOK_OBJ_ENTRY) * count); - // We need to zero out the last entry... Since the memcopy - // does not zero it out... - memset((char *)&global_shm->publ_tok_objs[global_shm->num_publ_tok_obj+1], 0, - sizeof(TOK_OBJ_ENTRY)); - } - else { - memset((char *)&global_shm->publ_tok_objs[global_shm->num_publ_tok_obj], 0, - sizeof(TOK_OBJ_ENTRY)); - } - } - - // - // object list is still sorted...so no need to re-sort - // - - return CKR_OK; -} - - -// -// -CK_RV -object_mgr_check_shm( OBJECT *obj ) -{ - TOK_OBJ_ENTRY * entry = NULL; - CK_BBOOL priv; - CK_ULONG index; - CK_RV rc; - - - // the calling routine is responsible for locking the global_shm mutex - // - - 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){ - OCK_LOG_ERR(ERR_FUNCTION_FAILED); - 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){ - OCK_LOG_ERR(ERR_FUNCTION_FAILED); - 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( obj ); - return rc; -} - - -// I'd use the standard bsearch() routine but I want an index, not a pointer. -// Converting the pointer to an index might cause problems when switching -// to a 64-bit environment... -// -CK_RV -object_mgr_search_shm_for_obj( TOK_OBJ_ENTRY * obj_list, - CK_ULONG lo, - CK_ULONG hi, - OBJECT * obj, - CK_ULONG * index ) -{ -// SAB XXX reduce the search time since this is what seems to be burning cycles - CK_ULONG idx; - if ( obj->index == 0 ) { - for (idx=0;idx<=hi;idx++){ - if (memcmp(obj->name, obj_list[idx].name,8) == 0) { - *index = idx; - obj->index = idx; - return CKR_OK ; - } - } - } else { - // SAB better double check - if ( memcmp(obj->name, obj_list[obj->index].name,8) == 0 ){ - *index = obj->index; - return CKR_OK ; - } else { // something is hosed.. go back to the brute force method - for (idx=0;idx<=hi;idx++){ - if (memcmp(obj->name, obj_list[idx].name,8) == 0) { - *index = idx; - obj->index = idx; - return CKR_OK ; - } - } - } - } - OCK_LOG_ERR(ERR_FUNCTION_FAILED); - return CKR_FUNCTION_FAILED; -} - - -// -// -CK_RV -object_mgr_sort_priv_shm( void ) -{ - // for now, we assume the list is sorted by design. this is not unreasonable - // since new object handles are assigned in increasing order. problems - // will arise after 36^8 token objects have been created... - // - return CKR_OK; -} - - -// -// -CK_RV -object_mgr_sort_publ_shm( void ) -{ - // for now, we assume the list is sorted by design. this is not unreasonable - // since new object handles are assigned in increasing order. problems - // will arise after 36^8 token objects have been created... - // - return CKR_OK; -} - - -// this routine scans the local token object lists and updates any objects that -// have changed. it also adds any new token objects that have been added by -// other processes and deletes any objects that have been deleted by other -// processes -// -CK_RV -object_mgr_update_from_shm( void ) -{ - object_mgr_update_publ_tok_obj_from_shm(); - object_mgr_update_priv_tok_obj_from_shm(); - - return CKR_OK; -} - -void -delete_objs_from_btree_cb(void *node, unsigned long obj_handle, void *p3) -{ - struct update_tok_obj_args * ua = (struct update_tok_obj_args *)p3; - TOK_OBJ_ENTRY * shm_te = NULL; - OBJECT * obj = (OBJECT *)node; - CK_ULONG index; - - /* for each TOK_OBJ_ENTRY in the SHM list */ - for (index = 0; index < *(ua->num_entries); index++) { - shm_te = &(ua->entries[index]); - - /* found it, return */ - if (!memcmp(obj->name, shm_te->name, 8)) { - return; - } - } - - /* didn't find it in SHM, delete it from its btree */ - bt_node_free(ua->t, obj_handle, object_free); -} - -void -find_by_name_cb(void *node, unsigned long obj_handle, void *p3) -{ - OBJECT *obj = (OBJECT *)node; - struct find_by_name_args *fa = (struct find_by_name_args *)p3; - - if (fa->done) - return; - - if (!memcmp(obj->name, fa->name, 8)) { - fa->done = TRUE; - } -} - -CK_RV -object_mgr_update_publ_tok_obj_from_shm() -{ - struct update_tok_obj_args ua; - struct find_by_name_args fa; - TOK_OBJ_ENTRY * shm_te = NULL; - CK_ULONG index; - OBJECT * new_obj; - - ua.entries = global_shm->publ_tok_objs; - ua.num_entries = &(global_shm->num_publ_tok_obj); - ua.t = &publ_token_obj_btree; - - /* delete any objects not in SHM from the btree */ - bt_for_each_node(&publ_token_obj_btree, delete_objs_from_btree_cb, &ua); - - /* for each item in SHM, add it to the btree if its not there */ - for (index = 0; index < global_shm->num_publ_tok_obj; index++) { - shm_te = &global_shm->publ_tok_objs[index]; - - fa.done = FALSE; - fa.name = shm_te->name; - - /* find an object from SHM in the btree */ - bt_for_each_node(&publ_token_obj_btree, find_by_name_cb, &fa); - - /* we didn't find it in the btree, so add it */ - if (fa.done == FALSE) { - new_obj = (OBJECT *)malloc(sizeof(OBJECT)); - memset( new_obj, 0x0, sizeof(OBJECT) ); - - memcpy( new_obj->name, shm_te->name, 8 ); - reload_token_object( new_obj ); - bt_node_add(&publ_token_obj_btree, new_obj); - } - } - - return CKR_OK; -} - -CK_RV -object_mgr_update_priv_tok_obj_from_shm() -{ - struct update_tok_obj_args ua; - struct find_by_name_args fa; - TOK_OBJ_ENTRY * shm_te = NULL; - CK_ULONG index; - OBJECT * new_obj; - - // SAB XXX don't bother doing this call if we are not in the correct - // login state - if ( !(global_login_state == CKS_RW_USER_FUNCTIONS || - global_login_state == CKS_RO_USER_FUNCTIONS) ) { - return CKR_OK; - } - - ua.entries = global_shm->priv_tok_objs; - ua.num_entries = &(global_shm->num_priv_tok_obj); - ua.t = &priv_token_obj_btree; - - /* delete any objects not in SHM from the btree */ - bt_for_each_node(&priv_token_obj_btree, delete_objs_from_btree_cb, &ua); - - /* for each item in SHM, add it to the btree if its not there */ - for (index = 0; index < global_shm->num_priv_tok_obj; index++) { - shm_te = &global_shm->priv_tok_objs[index]; - - fa.done = FALSE; - fa.name = shm_te->name; - - /* find an object from SHM in the btree */ - bt_for_each_node(&priv_token_obj_btree, find_by_name_cb, &fa); - - /* we didn't find it in the btree, so add it */ - if (fa.done == FALSE) { - new_obj = (OBJECT *)malloc(sizeof(OBJECT)); - memset( new_obj, 0x0, sizeof(OBJECT) ); - - memcpy( new_obj->name, shm_te->name, 8 ); - reload_token_object( new_obj ); - bt_node_add(&priv_token_obj_btree, new_obj); - } - } - - return CKR_OK; -} - -// SAB FIXME FIXME - -void -purge_map_by_type_cb(void *node, unsigned long map_handle, void *p3) -{ - OBJECT_MAP *map = (OBJECT_MAP *)node; - SESS_OBJ_TYPE type = *(SESS_OBJ_TYPE *)p3; - - if (type == PRIVATE) { - if (map->is_private) { - bt_node_free(&object_map_btree, map_handle, free); - } - } else if (type == PUBLIC) { - if (!map->is_private) { - bt_node_free(&object_map_btree, map_handle, free); - } - } -} - -CK_BBOOL -object_mgr_purge_map( - SESSION * sess, - SESS_OBJ_TYPE type ) -{ - if (pthread_rwlock_wrlock(&obj_list_rw_mutex)) { - OCK_LOG_ERR(ERR_FUNCTION_FAILED); - return CKR_FUNCTION_FAILED; - } - - bt_for_each_node(&object_map_btree, purge_map_by_type_cb, &type); - - pthread_rwlock_unlock(&obj_list_rw_mutex); - - return TRUE; -} - -#ifdef DEBUG -void -dump_shm(const char *s) -{ - CK_ULONG i; - OCK_LOG_DEBUG("%s: dump_shm priv:", s); - - for (i = 0; i < global_shm->num_priv_tok_obj; i++) { - OCK_LOG_DEBUG("[%lu]: %.8s", i, global_shm->priv_tok_objs[i].name); - } - OCK_LOG_DEBUG("%s: dump_shm publ:", s); - for (i = 0; i < global_shm->num_publ_tok_obj; i++) { - OCK_LOG_DEBUG("[%lu]: %.8s", i, global_shm->publ_tok_objs[i].name); - } -} -#endif diff --git a/usr/lib/pkcs11/common/obj_mgr.c b/usr/lib/pkcs11/common/obj_mgr.c index 98c3d42..92c11c2 100755 --- a/usr/lib/pkcs11/common/obj_mgr.c +++ b/usr/lib/pkcs11/common/obj_mgr.c @@ -339,6 +339,15 @@ object_mgr_add( SESSION * sess, OCK_LOG_ERR(ERR_OBJ_CREATE); goto done; } + + if (token_specific.t_object_add != NULL) { + rc = token_specific.t_object_add(o); + if (rc != CKR_OK) { + OCK_LOG_ERR(ERR_OBJ_CREATE); + goto done; + } + } + // check whether session has permissions to create the object, etc // // Object R/O R/W R/O R/W R/W commit ce8de9df2c93ad93f07b002fed6c0f59ce79bcda Author: Joy Latten Date: Wed Nov 13 15:23:52 2013 -0600 Objects were not being encrypted and saved to disk for secure key token. Needed to call encrypt_data_with_clear_key() and let it determine if clear key or secure key and do appropriate actions. Signed-off-by: Joy Latten diff --git a/usr/lib/pkcs11/common/loadsave.c b/usr/lib/pkcs11/common/loadsave.c index b564de0..d0d0673 100755 --- a/usr/lib/pkcs11/common/loadsave.c +++ b/usr/lib/pkcs11/common/loadsave.c @@ -965,7 +965,7 @@ CK_RV save_private_token_object(OBJECT * obj) add_pkcs_padding(clear + clear_len, block_size, clear_len, padded_len); - rc = encrypt_data(key, key_len, + rc = encrypt_data_with_clear_key(key, key_len, token_specific.data_store.obj_initial_vector, clear, padded_len, cipher, &cipher_len); if (rc != CKR_OK) { @@ -1227,7 +1227,7 @@ CK_RV restore_private_token_object(CK_BYTE * data, CK_ULONG len, OBJECT * pObj) } memcpy(key, master_key, key_len); - rc = decrypt_data(key, key_len, + rc = decrypt_data_with_clear_key(key, key_len, token_specific.data_store.obj_initial_vector, data, len, clear, &clear_len); if (rc != CKR_OK) { commit f4df4a49d478f9846199250a4e7cda6135ff234f Author: Joy Latten Date: Wed Nov 13 15:59:59 2013 -0600 CCA token was putting incorrect OID info into CKA_ECDSA_PARAMS. This attribute must be passed in by user when generating EC keypair and should not be over-written. Since CKA_EC_POINT is for public key, does not require being in private key. Created a routine to get signature length when length only. Signed-off-by: Joy Latten diff --git a/usr/lib/pkcs11/cca_stdll/cca_specific.c b/usr/lib/pkcs11/cca_stdll/cca_specific.c index be4073b..f4bb76c 100644 --- a/usr/lib/pkcs11/cca_stdll/cca_specific.c +++ b/usr/lib/pkcs11/cca_stdll/cca_specific.c @@ -1340,6 +1340,7 @@ token_create_ec_keypair(TEMPLATE *publ_tmpl, CK_BYTE q[CCATOK_EC_MAX_Q_LEN]; CK_BBOOL found = FALSE; CK_RV rv; + CK_ATTRIBUTE *attr = NULL; /* * The token includes the header section first, @@ -1347,8 +1348,14 @@ token_create_ec_keypair(TEMPLATE *publ_tmpl, * and the public key section last. */ + /* The pkcs#11v2.20: + * CKA_ECDSA_PARAMS must be in public key's template when + * generating key pair and added to private key template. + * CKA_EC_POINT added to public key when key is generated. + */ + /* - * Get Q data for public and private key. + * Get Q data for public key. */ pubkey_offset = cca_ec_publkey_offset(tok); @@ -1370,41 +1377,14 @@ token_create_ec_keypair(TEMPLATE *publ_tmpl, return rv; } - if ((rv = build_update_attribute(priv_tmpl, CKA_EC_POINT, q, q_len))) - { - DBG("Build and update attribute for q failed rv=0x%lx\n", rv); - return rv; - } - - /* - * Get ECDSA PAMRAMS for both keys. - */ - p_len_offset = pubkey_offset + CCA_PUBL_P_LEN_OFFSET; - p_len = *(uint16_t *)&tok[p_len_offset]; - p_len = ntohs(p_len); - - for (i = 0; i < NUMEC; i++) { - if (p_len == der_ec_supported[i].len_bits) { - found = TRUE; - break; - } - } - - if(found == FALSE) { - DBG("The p len %lx is not valid.\n", p_len); - return CKR_FUNCTION_FAILED; - } - - if ((rv = build_update_attribute(publ_tmpl, CKA_ECDSA_PARAMS, - der_ec_supported[i].data, - der_ec_supported[i].data_size))) { - DBG("Build and update attribute for der data failed rv=0x%lx\n", rv); - return rv; + /* Add ec params to private key */ + if (!template_attribute_find(publ_tmpl, CKA_ECDSA_PARAMS, &attr)) { + OCK_LOG_ERR(ERR_TEMPLATE_INCOMPLETE); + return CKR_TEMPLATE_INCOMPLETE; } if ((rv = build_update_attribute(priv_tmpl, CKA_ECDSA_PARAMS, - der_ec_supported[i].data, - der_ec_supported[i].data_size))) { + attr->pValue, attr->ulValueLen))) { DBG("Build and update attribute for der data failed rv=0x%lx\n", rv); return rv; } @@ -2180,3 +2160,40 @@ token_specific_object_add(OBJECT *object) return CKR_OK; } + +CK_RV +get_ecsiglen(OBJECT *key_obj, CK_ULONG *size) +{ + CK_BBOOL flag; + CK_ATTRIBUTE *attr = NULL; + int i; + + flag = template_attribute_find( key_obj->template, + CKA_ECDSA_PARAMS, &attr ); + if (flag == FALSE) { + OCK_LOG_ERR(ERR_FUNCTION_FAILED); + return CKR_FUNCTION_FAILED; + } + + /* loop thru supported curves to find the size. + * both pkcs#11v2.20 and CCA expect the signature length to be + * twice the length of p. + * (See EC Signatures in pkcs#11v2.20 and docs for CSNDDSG.) + */ + for (i = 0; i < NUMEC; i++) { + if ((memcmp(attr->pValue, der_ec_supported[i].data, + attr->ulValueLen) == 0)) { + *size = der_ec_supported[i].len_bits; + /* round up if necessary */ + if ((*size % 8) == 0) + *size = (*size / 8) * 2; + else + *size = ((*size / 8) + 1) * 2; + OCK_LOG_DEBUG("getlen, curve = %d, size = %d\n", der_ec_supported[i].len_bits, *size); + return CKR_OK; + } + } + + OCK_LOG_ERR(ERR_MECHANISM_PARAM_INVALID); + return CKR_MECHANISM_PARAM_INVALID; +} diff --git a/usr/lib/pkcs11/common/mech_ec.c b/usr/lib/pkcs11/common/mech_ec.c index cf1c140..aab11b8 100644 --- a/usr/lib/pkcs11/common/mech_ec.c +++ b/usr/lib/pkcs11/common/mech_ec.c @@ -75,8 +75,7 @@ ec_sign( SESSION *sess, CK_ULONG *out_data_len ) { OBJECT *key_obj = NULL; - CK_ATTRIBUTE *attr = NULL; - CK_ULONG public_key_len; + CK_ULONG plen; CK_BBOOL flag; CK_RV rc; @@ -91,23 +90,21 @@ ec_sign( SESSION *sess, return rc; } - flag = template_attribute_find( key_obj->template, - CKA_EC_POINT, &attr ); - if (flag == FALSE) - return CKR_FUNCTION_FAILED; - else - public_key_len = attr->ulValueLen; + rc = get_ecsiglen(key_obj, &plen); + if (rc != CKR_OK) { + OCK_LOG_ERR(ERR_FUNCTION_FAILED); + return rc; + } if (length_only == TRUE) { - *out_data_len = public_key_len; + *out_data_len = plen; return CKR_OK; } - if (*out_data_len < public_key_len) { + if (*out_data_len < plen) { OCK_LOG_ERR(ERR_BUFFER_TOO_SMALL); return CKR_BUFFER_TOO_SMALL; } - *out_data_len = public_key_len; rc = ckm_ec_sign( in_data, in_data_len, out_data, out_data_len, key_obj ); @@ -160,8 +157,7 @@ ec_verify(SESSION *sess, CK_ULONG sig_len ) { OBJECT *key_obj = NULL; - CK_ATTRIBUTE *attr = NULL; - CK_ULONG public_key_len; + CK_ULONG plen; CK_BBOOL flag; CK_RV rc; @@ -171,16 +167,16 @@ ec_verify(SESSION *sess, OCK_LOG_ERR(ERR_OBJMGR_FIND_MAP); return rc; } - flag = template_attribute_find( key_obj->template, - CKA_EC_POINT, &attr ); - if (flag == FALSE) - return CKR_FUNCTION_FAILED; - else - public_key_len = attr->ulValueLen; + + rc = get_ecsiglen(key_obj, &plen); + if (rc != CKR_OK) { + OCK_LOG_ERR(ERR_FUNCTION_FAILED); + return rc; + } // check input data length restrictions // - if (sig_len > public_key_len){ + if (sig_len > plen){ OCK_LOG_ERR(ERR_SIGNATURE_LEN_RANGE); return CKR_SIGNATURE_LEN_RANGE; } commit b3c5e1635e1dd25d73f57b206c390719dac4b5f8 Author: Joy Latten Date: Wed Oct 2 17:15:34 2013 -0500 The sha256 in CCA (CSNBOWH) can take input larger than 32MB. Signed-off-by: Joy Latten diff --git a/usr/lib/pkcs11/cca_stdll/cca_specific.c b/usr/lib/pkcs11/cca_stdll/cca_specific.c index bfee04e..be4073b 100644 --- a/usr/lib/pkcs11/cca_stdll/cca_specific.c +++ b/usr/lib/pkcs11/cca_stdll/cca_specific.c @@ -1675,9 +1675,7 @@ token_specific_sha2_update(DIGEST_CONTEXT *c, CK_BYTE *in_data, CK_ULONG in_data DBG("update %lu", in_data_len); - if (in_data_len > CCA_MAX_SHA256_DATA_LEN) - return CKR_DATA_LEN_RANGE; - else if (!in_data) + if (!in_data) goto done; cca_ctx = (struct cca_sha256_ctx *)c->context; diff --git a/usr/lib/pkcs11/cca_stdll/defs.h b/usr/lib/pkcs11/cca_stdll/defs.h index 927cf8e..19e14dd 100755 --- a/usr/lib/pkcs11/cca_stdll/defs.h +++ b/usr/lib/pkcs11/cca_stdll/defs.h @@ -18,7 +18,6 @@ #define MAX_PIN_LEN 128 #define MIN_PIN_LEN 4 -#define CCA_MAX_SHA256_DATA_LEN (32 * 1024 * 1024 - 64) /* 32MB - 64 */ #define CCA_CHAIN_VECTOR_LEN 128 #define CCA_MAX_TAIL_LEN 64 #define CCA_HASH_PART_FIRST 0