diff --git a/opencryptoki-3.0-bz1033284.patch b/opencryptoki-3.0-bz1033284.patch new file mode 100644 index 0000000..0d133db --- /dev/null +++ b/opencryptoki-3.0-bz1033284.patch @@ -0,0 +1,2787 @@ +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 diff --git a/opencryptoki.spec b/opencryptoki.spec index 8b37059..aae6fa7 100644 --- a/opencryptoki.spec +++ b/opencryptoki.spec @@ -3,7 +3,7 @@ Name: opencryptoki Summary: Implementation of the PKCS#11 (Cryptoki) specification v2.11 Version: 3.0 -Release: 5%{?dist} +Release: 6%{?dist} License: CPL Group: System Environment/Base URL: http://sourceforge.net/projects/opencryptoki @@ -20,6 +20,9 @@ Patch2: %{name}-3.0-unit.patch # https://bugzilla.redhat.com/show_bug.cgi?id=1001729 # http://sourceforge.net/p/opencryptoki/opencryptoki/ci/b50eb39e3cf8ccfdb735fbddfcdae10bdb70e1c4/ Patch3: opencryptoki-3.0-opencryptoki-man.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=1033284 +# post-3.0 upstream fixes +Patch4: opencryptoki-3.0-bz1033284.patch Requires(pre): shadow-utils coreutils sed BuildRequires: openssl-devel BuildRequires: trousers-devel @@ -163,6 +166,7 @@ cryptographic hardware such as IBM 4764 or 4765 that uses the %patch1 -p1 -b .pkcsconf-man %patch2 -p1 -b .unit %patch3 -p1 -b .opencryptoki-man +%patch4 -p1 -b .bz1033284 # Upstream tarball has unnecessary executable perms set on the sources find . -name '*.[ch]' -print0 | xargs -0 chmod -x @@ -293,6 +297,9 @@ exit 0 %changelog +* Fri Nov 22 2013 Dan Horák - 3.0-6 +- apply post-3.0 fixes (#1033284) + * Tue Nov 19 2013 Dan Horák - 3.0-5 - update opencryptoki man page (#1001729)