# # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # include $(SRC)/lib/Makefile.lib # Hammerhead: amd64-only SUBDIRS = $(MACH64) all : TARGET= all clean : TARGET= clean clobber : TARGET= clobber install : TARGET= install .KEEP_STATE: all clean clobber install: $(SUBDIRS) $(SUBDIRS): FRC @cd $@; pwd; $(MAKE) $(TARGET) FRC: # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # Copyright 2018 Jason King # # Copyright (c) 2018, Joyent, Inc. LIBRARY = pkcs11_tpm.a VERS = .1 RSA_DIR = $(SRC)/common/crypto/rsa RSA_FLAGS = -I$(RSA_DIR) BIGNUM_DIR = $(SRC)/common/bignum BIGNUM_FLAGS = -I$(BIGNUM_DIR) PADDING_DIR = $(SRC)/common/crypto/padding PADDING_FLAGS = -I$(PADDING_DIR) SOFTCRYPTOFLAGS = $(RSA_FLAGS) $(PADDING_FLAGS) $(BIGNUM_FLAGS) OBJECTS= api_interface.o \ apiutil.o \ asn1.o \ cert.o \ data_obj.o \ decr_mgr.o \ dig_mgr.o \ encr_mgr.o \ globals.o \ hwf_obj.o \ key.o \ key_mgr.o \ loadsave.o \ log.o \ mech_md5.o \ mech_rsa.o \ mech_sha.o \ new_host.o \ obj_mgr.o \ object.o \ sess_mgr.o \ sign_mgr.o \ template.o \ tpm_specific.o \ utility.o \ verify_mgr.o include $(SRC)/lib/Makefile.lib SRCDIR= ../common SRCS= $(OBJECTS:%.o=$(SRCDIR)/%.c) # set signing mode POST_PROCESS_SO += ; $(ELFSIGN_CRYPTO) ROOTLIBDIR=$(ROOT)/usr/lib/security # Hammerhead: 64-bit only - flatten security library path ROOTLIBDIR64=$(ROOT)/usr/lib/security LIBS=$(DYNLIB) $(DYNLIB64) TSSROOT=$(ADJUNCT_PROTO) TSPILIBDIR=$(TSSROOT)/usr/lib TSPIINCDIR=$(TSSROOT)/usr/include TSSLIB=-L$(TSPILIBDIR) TSSLIB64=-L$(TSPILIBDIR)/$(MACH64) TSSINC=-I$(TSPIINCDIR) LDLIBS += $(TSSLIB) -L$(ADJUNCT_PROTO)/lib -lc -luuid -lmd -ltspi -lsoftcrypto # Hammerhead: GNU ld needs -Bsymbolic so provider's C_* function table # binds to its own definitions, not libpkcs11's (prevents infinite recursion) DYNFLAGS += -Wl,-Bsymbolic CPPFLAGS += -D_POSIX_PTHREAD_SEMANTICS $(TSSINC) $(SOFTCRYPTOFLAGS) CPPFLAGS64 += $(CPPFLAGS) CSTD= $(CSTD_GNU99) CERRWARN += -Wno-parentheses CERRWARN += $(CNOWARN_UNINIT) # not linted SMATCH=off .KEEP_STATE: all: $(LIBS) pics/%.o: $(SRCDIR)/%.c $(COMPILE.c) -o $@ $< $(POST_PROCESS_O) include $(SRC)/lib/Makefile.targ Common Public License Version 1.0 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. PKCS11 TPM PROVIDER LIBRARY (PKCS11_TPM) # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # include ../Makefile.com include $(SRC)/lib/Makefile.lib.64 TSSLIB=$(TSSLIB64) install: all $(ROOTLIBS64) $(ROOTLINKS64) /* * Common Public License Version 0.5 * * THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF * THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, * REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES * RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. * * 1. DEFINITIONS * * "Contribution" means: * a) in the case of the initial Contributor, the * initial code and documentation distributed under * this Agreement, and * * b) in the case of each subsequent Contributor: * i) changes to the Program, and * ii) additions to the Program; * * where such changes and/or additions to the Program * originate from and are distributed by that * particular Contributor. A Contribution 'originates' * from a Contributor if it was added to the Program * by such Contributor itself or anyone acting on such * Contributor's behalf. Contributions do not include * additions to the Program which: (i) are separate * modules of software distributed in conjunction with * the Program under their own license agreement, and * (ii) are not derivative works of the Program. * * * "Contributor" means any person or entity that distributes * the Program. * * "Licensed Patents " mean patent claims licensable by a * Contributor which are necessarily infringed by the use or * sale of its Contribution alone or when combined with the * Program. * * "Program" means the Contributions distributed in * accordance with this Agreement. * * "Recipient" means anyone who receives the Program under * this Agreement, including all Contributors. * * 2. GRANT OF RIGHTS * * a) Subject to the terms of this Agreement, each * Contributor hereby grants Recipient a * no - exclusive, worldwide, royalt - free copyright * license to reproduce, prepare derivative works of, * publicly display, publicly perform, distribute and * sublicense the Contribution of such Contributor, if * any, and such derivative works, in source code and * object code form. * * b) Subject to the terms of this Agreement, each * Contributor hereby grants Recipient a * no - exclusive, worldwide, royalt - free patent * license under Licensed Patents to make, use, sell, * offer to sell, import and otherwise transfer the * Contribution of such Contributor, if any, in source * code and object code form. This patent license * shall apply to the combination of the Contribution * and the Program if, at the time the Contribution is * added by the Contributor, such addition of the * Contribution causes such combination to be covered * by the Licensed Patents. The patent license shall * not apply to any other combinations which include * the Contribution. No hardware per se is licensed * hereunder. * * c) Recipient understands that although each * Contributor grants the licenses to its * Contributions set forth herein, no assurances are * provided by any Contributor that the Program does * not infringe the patent or other intellectual * property rights of any other entity. Each * Contributor disclaims any liability to Recipient * for claims brought by any other entity based on * infringement of intellectual property rights or * otherwise. As a condition to exercising the rights * and licenses granted hereunder, each Recipient * hereby assumes sole responsibility to secure any * other intellectual property rights needed, if any. * * For example, if a third party patent license is * required to allow Recipient to distribute the * Program, it is Recipient's responsibility to * acquire that license before distributing the * Program. * * d) Each Contributor represents that to its * knowledge it has sufficient copyright rights in its * Contribution, if any, to grant the copyright * license set forth in this Agreement. * * 3. REQUIREMENTS * * A Contributor may choose to distribute the Program in * object code form under its own license agreement, provided * that: * a) it complies with the terms and conditions of * this Agreement; and * * b) its license agreement: * i) effectively disclaims on behalf of all * Contributors all warranties and conditions, express * and implied, including warranties or conditions of * title and no - infringement, and implied warranties * or conditions of merchantability and fitness for a * particular purpose; * * ii) effectively excludes on behalf of all * Contributors all liability for damages, including * direct, indirect, special, incidental and * consequential damages, such as lost profits; * * iii) states that any provisions which differ from * this Agreement are offered by that Contributor * alone and not by any other party; and * * iv) states that source code for the Program is * available from such Contributor, and informs * licensees how to obtain it in a reasonable manner * on or through a medium customarily used for * software exchange. * * When the Program is made available in source code form: * a) it must be made available under this Agreement; * and * b) a copy of this Agreement must be included with * each copy of the Program. * * Contributors may not remove or alter any copyright notices * contained within the Program. * * Each Contributor must identify itself as the originator of * its Contribution, if any, in a manner that reasonably * allows subsequent Recipients to identify the originator of * the Contribution. * * * 4. COMMERCIAL DISTRIBUTION * * Commercial distributors of software may accept certain * responsibilities with respect to end users, business * partners and the like. While this license is intended to * facilitate the commercial use of the Program, the * Contributor who includes the Program in a commercial * product offering should do so in a manner which does not * create potential liability for other Contributors. * Therefore, if a Contributor includes the Program in a * commercial product offering, such Contributor ("Commercial * Contributor") hereby agrees to defend and indemnify every * other Contributor ("Indemnified Contributor") against any * losses, damages and costs (collectively "Losses") arising * from claims, lawsuits and other legal actions brought by a * third party against the Indemnified Contributor to the * extent caused by the acts or omissions of such Commercial * Contributor in connection with its distribution of the * Program in a commercial product offering. The obligations * in this section do not apply to any claims or Losses * relating to any actual or alleged intellectual property * infringement. In order to qualify, an Indemnified * Contributor must: a) promptly notify the Commercial * Contributor in writing of such claim, and b) allow the * Commercial Contributor to control, and cooperate with the * Commercial Contributor in, the defense and any related * settlement negotiations. The Indemnified Contributor may * participate in any such claim at its own expense. * * * For example, a Contributor might include the Program in a * commercial product offering, Product X. That Contributor * is then a Commercial Contributor. If that Commercial * Contributor then makes performance claims, or offers * warranties related to Product X, those performance claims * and warranties are such Commercial Contributor's * responsibility alone. Under this section, the Commercial * Contributor would have to defend claims against the other * Contributors related to those performance claims and * warranties, and if a court requires any other Contributor * to pay any damages as a result, the Commercial Contributor * must pay those damages. * * * 5. NO WARRANTY * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE * PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR * IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR * CONDITIONS OF TITLE, NO - INFRINGEMENT, MERCHANTABILITY OR * FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely * responsible for determining the appropriateness of using * and distributing the Program and assumes all risks * associated with its exercise of rights under this * Agreement, including but not limited to the risks and * costs of program errors, compliance with applicable laws, * damage to or loss of data, programs or equipment, and * unavailability or interruption of operations. * * 6. DISCLAIMER OF LIABILITY * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER * RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION * LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE * OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * 7. GENERAL * * If any provision of this Agreement is invalid or * unenforceable under applicable law, it shall not affect * the validity or enforceability of the remainder of the * terms of this Agreement, and without further action by the * parties hereto, such provision shall be reformed to the * minimum extent necessary to make such provision valid and * enforceable. * * * If Recipient institutes patent litigation against a * Contributor with respect to a patent applicable to * software (including a cros - claim or counterclaim in a * lawsuit), then any patent licenses granted by that * Contributor to such Recipient under this Agreement shall * terminate as of the date such litigation is filed. In * addition, If Recipient institutes patent litigation * against any entity (including a cros - claim or * counterclaim in a lawsuit) alleging that the Program * itself (excluding combinations of the Program with other * software or hardware) infringes such Recipient's * patent(s), then such Recipient's rights granted under * Section 2(b) shall terminate as of the date such * litigation is filed. * * All Recipient's rights under this Agreement shall * terminate if it fails to comply with any of the material * terms or conditions of this Agreement and does not cure * such failure in a reasonable period of time after becoming * aware of such noncompliance. If all Recipient's rights * under this Agreement terminate, Recipient agrees to cease * use and distribution of the Program as soon as reasonably * practicable. However, Recipient's obligations under this * Agreement and any licenses granted by Recipient relating * to the Program shall continue and survive. * * Everyone is permitted to copy and distribute copies of * this Agreement, but in order to avoid inconsistency the * Agreement is copyrighted and may only be modified in the * following manner. The Agreement Steward reserves the right * to publish new versions (including revisions) of this * Agreement from time to time. No one other than the * Agreement Steward has the right to modify this Agreement. * * IBM is the initial Agreement Steward. IBM may assign the * responsibility to serve as the Agreement Steward to a * suitable separate entity. Each new version of the * Agreement will be given a distinguishing version number. * The Program (including Contributions) may always be * distributed subject to the version of the Agreement under * which it was received. In addition, after a new version of * the Agreement is published, Contributor may elect to * distribute the Program (including its Contributions) under * the new version. Except as expressly stated in Sections * 2(a) and 2(b) above, Recipient receives no rights or * licenses to the intellectual property of any Contributor * under this Agreement, whether expressly, by implication, * estoppel or otherwise. All rights in the Program not * expressly granted under this Agreement are reserved. * * * This Agreement is governed by the laws of the State of New * York and the intellectual property laws of the United * States of America. No party to this Agreement will bring a * legal action under this Agreement more than one year after * the cause of action arose. Each party waives its rights to * a jury trial in any resulting litigation. * * * * (C) COPYRIGHT International Business Machines Corp. 2001, 2002 */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include "tpmtok_int.h" #define LOG(x) logit(LOG_DEBUG, x) /* * NOTES: * In many cases the specificaiton does not allow returns * of CKR_ARGUMENTSB_BAD. We break the spec, since validation of parameters * to the function are best represented by this return code (where * specific RC's such as CKR_INVALID_SESSION do not exist). * NOTE NOTE NOTE NOTE * The parameter checking on the update operations may need to be * modified (as well as the encrypt/decrypt) to call the std API * anyway with sanatized parameters since on error, the encrypt/decrypt * sign operations are all supposed to complete. * Therefor the parameter checking here might need to be done in * the STDLL instead of the API. * This would affect ALL the Multipart operations which have * an init followed by one or more operations. * * Globals for the API */ API_Proc_Struct_t *Anchor = NULL; static unsigned int Initialized = 0; static pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER; struct ST_FCN_LIST FuncList; CK_FUNCTION_LIST PK11_Functions; extern pthread_rwlock_t obj_list_rw_mutex; static void tpmtoken_fork_prepare() { (void) pthread_mutex_lock(&global_mutex); (void) pthread_mutex_lock(&pkcs_mutex); (void) pthread_mutex_lock(&obj_list_mutex); (void) pthread_rwlock_wrlock(&obj_list_rw_mutex); (void) pthread_mutex_lock(&sess_list_mutex); (void) pthread_mutex_lock(&login_mutex); if (Anchor) { (void) pthread_mutex_lock(&Anchor->ProcMutex); (void) pthread_mutex_lock(&Anchor->SessListMutex); } } static void tpmtoken_fork_parent() { if (Anchor) { (void) pthread_mutex_unlock(&Anchor->SessListMutex); (void) pthread_mutex_unlock(&Anchor->ProcMutex); } (void) pthread_mutex_unlock(&login_mutex); (void) pthread_mutex_unlock(&sess_list_mutex); (void) pthread_rwlock_unlock(&obj_list_rw_mutex); (void) pthread_mutex_unlock(&obj_list_mutex); (void) pthread_mutex_unlock(&pkcs_mutex); (void) pthread_mutex_unlock(&global_mutex); } static void tpmtoken_fork_child() { if (Anchor) { (void) pthread_mutex_unlock(&Anchor->SessListMutex); (void) pthread_mutex_unlock(&Anchor->ProcMutex); } (void) pthread_mutex_unlock(&login_mutex); (void) pthread_mutex_unlock(&sess_list_mutex); (void) pthread_rwlock_unlock(&obj_list_rw_mutex); (void) pthread_mutex_unlock(&obj_list_mutex); (void) pthread_mutex_unlock(&pkcs_mutex); (void) pthread_mutex_unlock(&global_mutex); if (Anchor) { Terminate_All_Process_Sessions(); free(Anchor); Anchor = NULL; } if (FuncList.ST_Finalize) FuncList.ST_Finalize(0); logterm(); loginit(); } /*ARGSUSED*/ CK_RV C_CancelFunction(CK_SESSION_HANDLE hSession) { LOG("C_CancelFunction"); if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } return (CKR_FUNCTION_NOT_PARALLEL); } CK_RV C_CloseAllSessions(CK_SLOT_ID slotID) { Session_Struct_t *pCur, *pPrev; CK_RV rv; /* * Although why does modutil do a close all sessions. It is a single * application it can only close its sessions... * And all sessions should be closed anyhow. */ LOG("CloseAllSessions"); if (API_Initialized() == FALSE) return (CKR_CRYPTOKI_NOT_INITIALIZED); if (!global_shm->token_available || (slotID > NUMBER_SLOTS_MANAGED)) return (CKR_SLOT_ID_INVALID); /* * Proc Mutex is locked when we remove from the seesion list in * Close SEssion. Therefore we don't need to do any locking * the atomic operations are controled when we use the linked list */ pCur = (Anchor ? Anchor->SessListBeg : NULL); while (pCur) { /* * Session owned by the slot we are working on * There is a basic problem here. We are using th pCur * to point to the current one, however we delete it from * the linked list and can no longer go Forward. So we * have to use the fact that this is a doubly linked list * and get the previous pointer. After deletion, the next * pointer of this block will point to the next one in the * list. * If the value is Null, then this was the first one in * the list and we just set pCur to the SessListBeg. */ if (pCur->SltId == slotID) { pPrev = pCur->Previous; rv = C_CloseSession((CK_SESSION_HANDLE)pCur); if (rv == CKR_OK || rv == CKR_SESSION_CLOSED || rv == CKR_SESSION_HANDLE_INVALID) { if (pPrev == NULL) { pCur = Anchor->SessListBeg; } else { pCur = pPrev->Next; } } else { return (rv); } } else { pCur = pCur->Next; } } LOG("CloseAllSessions OK"); return (CKR_OK); } CK_RV C_CloseSession(CK_SESSION_HANDLE hSession) { CK_RV rv; Session_Struct_t *sessp; ST_SESSION_T rSession; LOG("C_CloseSession"); if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } /* Validate Session */ if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_CloseSession) { /* Map the Session to the slot session */ rv = FuncList.ST_CloseSession(rSession); if (rv == CKR_OK) { sessp = (Session_Struct_t *)hSession; RemoveFromSessionList(sessp); } } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_CopyObject( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phNewObject) { CK_RV rv; ST_SESSION_T rSession; LOG("C_CopyObject"); if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (!Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (!phNewObject) { return (CKR_ARGUMENTS_BAD); } /* * A null template with a count will cause the lower layer * to have problems. * Template with 0 count is not a problem. */ if (!pTemplate && ulCount) { return (CKR_ARGUMENTS_BAD); } if (FuncList.ST_CopyObject) { rv = FuncList.ST_CopyObject(rSession, hObject, pTemplate, ulCount, phNewObject); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_CreateObject( CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (! pTemplate) { return (CKR_TEMPLATE_INCOMPLETE); } if (ulCount == 0) { return (CKR_TEMPLATE_INCOMPLETE); } if (! phObject) { return (CKR_ARGUMENTS_BAD); } if (FuncList.ST_CreateObject) { // Map the Session to the slot session rv = FuncList.ST_CreateObject(rSession, pTemplate, ulCount, phObject); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (!Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_Decrypt) { rv = FuncList.ST_Decrypt(rSession, pEncryptedData, ulEncryptedDataLen, pData, pulDataLen); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_DecryptDigestUpdate( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (! pEncryptedPart || ! pulPartLen) { return (CKR_ARGUMENTS_BAD); } if (FuncList.ST_DecryptDigestUpdate) { rv = FuncList.ST_DecryptDigestUpdate(rSession, pEncryptedPart, ulEncryptedPartLen, pPart, pulPartLen); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_DecryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastPart, CK_ULONG_PTR pulLastPartLen) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } /* * It is acceptable to have a Null pointer for the data since * it is trying to get the length of the last part.... * The spec is unclear if a second call to Final is needed * if there is no data in the last part. */ if (! pulLastPartLen) { return (CKR_ARGUMENTS_BAD); } if (FuncList.ST_DecryptFinal) { rv = FuncList.ST_DecryptFinal(rSession, pLastPart, pulLastPartLen); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_DecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (! pMechanism) { return (CKR_MECHANISM_INVALID); } if (FuncList.ST_DecryptInit) { rv = FuncList.ST_DecryptInit(rSession, pMechanism, hKey); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_DecryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (!Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (!pEncryptedPart || !pulPartLen) { return (CKR_ARGUMENTS_BAD); } if (FuncList.ST_DecryptUpdate) { rv = FuncList.ST_DecryptUpdate(rSession, pEncryptedPart, ulEncryptedPartLen, pPart, pulPartLen); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } // Validate Session if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } // May have to let these go through and let the STDLL handle them if (! pEncryptedPart || ! pulPartLen) { return (CKR_ARGUMENTS_BAD); } // Get local pointers to session if (FuncList.ST_DecryptVerifyUpdate) { // Map the Session to the slot session rv = FuncList.ST_DecryptVerifyUpdate(rSession, pEncryptedPart, ulEncryptedPartLen, pPart, pulPartLen); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_DeriveKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (!Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (!pMechanism) { return (CKR_MECHANISM_INVALID); } if (!pTemplate && ulAttributeCount) { return (CKR_ARGUMENTS_BAD); } if (FuncList.ST_DeriveKey) { rv = FuncList.ST_DeriveKey(rSession, pMechanism, hBaseKey, pTemplate, ulAttributeCount, phKey); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (!Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_DestroyObject) { rv = FuncList.ST_DestroyObject(rSession, hObject); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_Digest(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (!Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_Digest) { rv = FuncList.ST_Digest(rSession, pData, ulDataLen, pDigest, pulDigestLen); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_DigestEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! pPart || ! pulEncryptedPartLen) { return (CKR_ARGUMENTS_BAD); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_DigestEncryptUpdate) { rv = FuncList.ST_DigestEncryptUpdate(rSession, pPart, ulPartLen, pEncryptedPart, pulEncryptedPartLen); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_DigestFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! pulDigestLen) { return (CKR_ARGUMENTS_BAD); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_DigestFinal) { rv = FuncList.ST_DigestFinal(rSession, pDigest, pulDigestLen); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_DigestInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! pMechanism) { return (CKR_MECHANISM_INVALID); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_DigestInit) { rv = FuncList.ST_DigestInit(rSession, pMechanism); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_DigestKey) { rv = FuncList.ST_DigestKey(rSession, hKey); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_DigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_DigestUpdate) { rv = FuncList.ST_DigestUpdate(rSession, pPart, ulPartLen); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } // Get local pointers to session if (FuncList.ST_Encrypt) { // Map the Session to the slot session rv = FuncList.ST_Encrypt(rSession, pData, ulDataLen, pEncryptedData, pulEncryptedDataLen); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_EncryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pulLastEncryptedPartLen) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_EncryptFinal) { rv = FuncList.ST_EncryptFinal(rSession, pLastEncryptedPart, pulLastEncryptedPartLen); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! pMechanism) { return (CKR_MECHANISM_INVALID); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_EncryptInit) { rv = FuncList.ST_EncryptInit(rSession, pMechanism, hKey); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_EncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (!pPart || !pulEncryptedPartLen) { return (CKR_ARGUMENTS_BAD); } if (!Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_EncryptUpdate) { rv = FuncList.ST_EncryptUpdate(rSession, pPart, ulPartLen, pEncryptedPart, pulEncryptedPartLen); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV do_finalize(CK_VOID_PTR pReserved) { if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (pReserved != NULL) { return (CKR_ARGUMENTS_BAD); } (void) pthread_mutex_lock(&global_mutex); if (Anchor) Terminate_All_Process_Sessions(); if (FuncList.ST_Finalize) FuncList.ST_Finalize(0); free(Anchor); Anchor = NULL; (void) pthread_mutex_unlock(&global_mutex); return (CKR_OK); } CK_RV C_Finalize(CK_VOID_PTR pReserved) { return (do_finalize(pReserved)); } CK_RV C_FindObjects(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject, CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! phObject || ! pulObjectCount) { return (CKR_ARGUMENTS_BAD); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_FindObjects) { rv = FuncList.ST_FindObjects(rSession, phObject, ulMaxObjectCount, pulObjectCount); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_FindObjectsFinal(CK_SESSION_HANDLE hSession) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_FindObjectsFinal) { rv = FuncList.ST_FindObjectsFinal(rSession); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_FindObjectsInit(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_FindObjectsInit) { rv = FuncList.ST_FindObjectsInit(rSession, pTemplate, ulCount); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_GenerateKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! pMechanism) { return (CKR_MECHANISM_INVALID); } if (! phKey) { return (CKR_ARGUMENTS_BAD); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_GenerateKey) { rv = FuncList.ST_GenerateKey(rSession, pMechanism, pTemplate, ulCount, phKey); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_GenerateKeyPair(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPublicKey, CK_OBJECT_HANDLE_PTR phPrivateKey) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! pMechanism) { return (CKR_MECHANISM_INVALID); } if (! phPublicKey || ! phPrivateKey) { return (CKR_ARGUMENTS_BAD); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_GenerateKeyPair) { rv = FuncList.ST_GenerateKeyPair(rSession, pMechanism, pPublicKeyTemplate, ulPublicKeyAttributeCount, pPrivateKeyTemplate, ulPrivateKeyAttributeCount, phPublicKey, phPrivateKey); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_GenerateRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR RandomData, CK_ULONG ulRandomLen) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! RandomData) return (CKR_ARGUMENTS_BAD); if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_GenerateRandom) { rv = FuncList.ST_GenerateRandom(rSession, RandomData, ulRandomLen); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_GetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! pTemplate) { return (CKR_TEMPLATE_INCOMPLETE); } if (ulCount == 0) { return (CKR_TEMPLATE_INCOMPLETE); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_GetAttributeValue) { rv = FuncList.ST_GetAttributeValue(rSession, hObject, pTemplate, ulCount); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList) { PK11_Functions.version.major = VERSION_MAJOR; PK11_Functions.version.minor = VERSION_MINOR; PK11_Functions.C_Initialize = C_Initialize; PK11_Functions.C_Finalize = C_Finalize; PK11_Functions.C_GetInfo = C_GetInfo; PK11_Functions.C_GetFunctionList = C_GetFunctionList; PK11_Functions.C_GetSlotList = C_GetSlotList; PK11_Functions.C_GetSlotInfo = C_GetSlotInfo; PK11_Functions.C_GetTokenInfo = C_GetTokenInfo; PK11_Functions.C_GetMechanismList = C_GetMechanismList; PK11_Functions.C_GetMechanismInfo = C_GetMechanismInfo; PK11_Functions.C_InitToken = C_InitToken; PK11_Functions.C_InitPIN = C_InitPIN; PK11_Functions.C_SetPIN = C_SetPIN; PK11_Functions.C_OpenSession = C_OpenSession; PK11_Functions.C_CloseSession = C_CloseSession; PK11_Functions.C_CloseAllSessions = C_CloseAllSessions; PK11_Functions.C_GetSessionInfo = C_GetSessionInfo; PK11_Functions.C_GetOperationState = C_GetOperationState; PK11_Functions.C_SetOperationState = C_SetOperationState; PK11_Functions.C_Login = C_Login; PK11_Functions.C_Logout = C_Logout; PK11_Functions.C_CreateObject = C_CreateObject; PK11_Functions.C_CopyObject = C_CopyObject; PK11_Functions.C_DestroyObject = C_DestroyObject; PK11_Functions.C_GetObjectSize = C_GetObjectSize; PK11_Functions.C_GetAttributeValue = C_GetAttributeValue; PK11_Functions.C_SetAttributeValue = C_SetAttributeValue; PK11_Functions.C_FindObjectsInit = C_FindObjectsInit; PK11_Functions.C_FindObjects = C_FindObjects; PK11_Functions.C_FindObjectsFinal = C_FindObjectsFinal; PK11_Functions.C_EncryptInit = C_EncryptInit; PK11_Functions.C_Encrypt = C_Encrypt; PK11_Functions.C_EncryptUpdate = C_EncryptUpdate; PK11_Functions.C_EncryptFinal = C_EncryptFinal; PK11_Functions.C_DecryptInit = C_DecryptInit; PK11_Functions.C_Decrypt = C_Decrypt; PK11_Functions.C_DecryptUpdate = C_DecryptUpdate; PK11_Functions.C_DecryptFinal = C_DecryptFinal; PK11_Functions.C_DigestInit = C_DigestInit; PK11_Functions.C_Digest = C_Digest; PK11_Functions.C_DigestUpdate = C_DigestUpdate; PK11_Functions.C_DigestKey = C_DigestKey; PK11_Functions.C_DigestFinal = C_DigestFinal; PK11_Functions.C_SignInit = C_SignInit; PK11_Functions.C_Sign = C_Sign; PK11_Functions.C_SignUpdate = C_SignUpdate; PK11_Functions.C_SignFinal = C_SignFinal; PK11_Functions.C_SignRecoverInit = C_SignRecoverInit; PK11_Functions.C_SignRecover = C_SignRecover; PK11_Functions.C_VerifyInit = C_VerifyInit; PK11_Functions.C_Verify = C_Verify; PK11_Functions.C_VerifyUpdate = C_VerifyUpdate; PK11_Functions.C_VerifyFinal = C_VerifyFinal; PK11_Functions.C_VerifyRecoverInit = C_VerifyRecoverInit; PK11_Functions.C_VerifyRecover = C_VerifyRecover; PK11_Functions.C_DigestEncryptUpdate = C_DigestEncryptUpdate; PK11_Functions.C_DecryptDigestUpdate = C_DecryptDigestUpdate; PK11_Functions.C_SignEncryptUpdate = C_SignEncryptUpdate; PK11_Functions.C_DecryptVerifyUpdate = C_DecryptVerifyUpdate; PK11_Functions.C_GenerateKey = C_GenerateKey; PK11_Functions.C_GenerateKeyPair = C_GenerateKeyPair; PK11_Functions.C_WrapKey = C_WrapKey; PK11_Functions.C_UnwrapKey = C_UnwrapKey; PK11_Functions.C_DeriveKey = C_DeriveKey; PK11_Functions.C_SeedRandom = C_SeedRandom; PK11_Functions.C_GenerateRandom = C_GenerateRandom; PK11_Functions.C_GetFunctionStatus = C_GetFunctionStatus; PK11_Functions.C_CancelFunction = C_CancelFunction; PK11_Functions.C_WaitForSlotEvent = C_WaitForSlotEvent; if (ppFunctionList) { (*ppFunctionList) = &PK11_Functions; return (CKR_OK); } else { return (CKR_ARGUMENTS_BAD); } } /*ARGSUSED*/ CK_RV C_GetFunctionStatus(CK_SESSION_HANDLE hSession) { if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } return (CKR_FUNCTION_NOT_PARALLEL); // PER Specification PG 170 } CK_RV C_GetInfo(CK_INFO_PTR pInfo) { TOKEN_DATA td; TSS_HCONTEXT hContext; if (! API_Initialized()) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! pInfo) { return (CKR_FUNCTION_FAILED); } (void) memset(pInfo, 0, sizeof (*pInfo)); pInfo->cryptokiVersion.major = 2; pInfo->cryptokiVersion.minor = 20; if (open_tss_context(&hContext) == 0) { /* * Only populate the TPM info if we can establish * a context, but don't return failure because * the framework needs to know some of the info. */ (void) token_get_tpm_info(hContext, &td); (void) Tspi_Context_Close(hContext); (void) memcpy(pInfo->manufacturerID, &(td.token_info.manufacturerID), sizeof (pInfo->manufacturerID) - 1); pInfo->flags = td.token_info.flags; } (void) strcpy((char *)pInfo->libraryDescription, "PKCS11 Interface for TPM"); pInfo->libraryVersion.major = 1; pInfo->libraryVersion.minor = 0; return (CKR_OK); } CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo) { CK_RV rv; if (API_Initialized() == FALSE) return (CKR_CRYPTOKI_NOT_INITIALIZED); if (!global_shm->token_available || (slotID > NUMBER_SLOTS_MANAGED)) return (CKR_SLOT_ID_INVALID); if (FuncList.ST_GetMechanismInfo) { rv = FuncList.ST_GetMechanismInfo(slotID, type, pInfo); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_GetMechanismList(CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount) { CK_RV rv; if (API_Initialized() == FALSE) return (CKR_CRYPTOKI_NOT_INITIALIZED); if (! pulCount) return (CKR_ARGUMENTS_BAD); if (!global_shm->token_available || (slotID > NUMBER_SLOTS_MANAGED)) return (CKR_SLOT_ID_INVALID); if (FuncList.ST_GetMechanismList) { rv = FuncList.ST_GetMechanismList(slotID, pMechanismList, pulCount); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } if (rv == CKR_OK) { if (pMechanismList) { unsigned long i; for (i = 0; i < *pulCount; i++) { logit(LOG_DEBUG, "Mechanism[%d] 0x%08X ", i, pMechanismList[i]); } } } return (rv); } CK_RV C_GetObjectSize(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! pulSize) { return (CKR_ARGUMENTS_BAD); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_GetObjectSize) { rv = FuncList.ST_GetObjectSize(rSession, hObject, pulSize); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_GetOperationState(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! pulOperationStateLen) { return (CKR_ARGUMENTS_BAD); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_GetOperationState) { rv = FuncList.ST_GetOperationState(rSession, pOperationState, pulOperationStateLen); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_GetSessionInfo(CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! pInfo) { return (CKR_ARGUMENTS_BAD); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_GetSessionInfo) { rv = FuncList.ST_GetSessionInfo(rSession, pInfo); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { if (API_Initialized() == FALSE) return (CKR_CRYPTOKI_NOT_INITIALIZED); if (!pInfo) return (CKR_FUNCTION_FAILED); if (!global_shm->token_available || (slotID > NUMBER_SLOTS_MANAGED)) return (CKR_SLOT_ID_INVALID); copy_slot_info(slotID, pInfo); return (CKR_OK); } /*ARGSUSED*/ CK_RV C_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount) { CK_ULONG count; CK_SLOT_INFO slotInfo; if (API_Initialized() == FALSE) return (CKR_CRYPTOKI_NOT_INITIALIZED); if (pulCount == NULL) return (CKR_FUNCTION_FAILED); count = 0; /* * If we can't talk to the TPM, present no slots */ if (!global_shm->token_available) { *pulCount = 0; return (CKR_OK); } copy_slot_info(TPM_SLOTID, &slotInfo); if ((slotInfo.flags & CKF_TOKEN_PRESENT)) count++; *pulCount = count; if (pSlotList == NULL) { return (CKR_OK); } else { if (*pulCount < count) return (CKR_BUFFER_TOO_SMALL); pSlotList[0] = TPM_SLOTID; } return (CKR_OK); } CK_RV C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo) { CK_RV rv; if (API_Initialized() == FALSE) return (CKR_CRYPTOKI_NOT_INITIALIZED); if (!pInfo) return (CKR_ARGUMENTS_BAD); if (!global_shm->token_available || (slotID > NUMBER_SLOTS_MANAGED)) return (CKR_SLOT_ID_INVALID); slotID = TPM_SLOTID; if (FuncList.ST_GetTokenInfo) { rv = FuncList.ST_GetTokenInfo(slotID, pInfo); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_Initialize(CK_VOID_PTR pVoid) { CK_RV rv = CKR_OK; CK_C_INITIALIZE_ARGS *pArg; extern CK_RV ST_Initialize(void *, CK_SLOT_ID, unsigned char *); (void) pthread_mutex_lock(&global_mutex); if (! Anchor) { Anchor = (API_Proc_Struct_t *)malloc( sizeof (API_Proc_Struct_t)); if (Anchor == NULL) { (void) pthread_mutex_unlock(&global_mutex); return (CKR_HOST_MEMORY); } } else { (void) pthread_mutex_unlock(&global_mutex); return (CKR_CRYPTOKI_ALREADY_INITIALIZED); } /* * if pVoid is NULL, then everything is OK. The applicaiton * will not be doing multi thread accesses. We can use the OS * locks anyhow. */ if (pVoid != NULL) { int supplied_ok; pArg = (CK_C_INITIALIZE_ARGS *)pVoid; /* * ALL supplied function pointers need to have the value * either NULL or no - NULL. */ supplied_ok = (pArg->CreateMutex == NULL && pArg->DestroyMutex == NULL && pArg->LockMutex == NULL && pArg->UnlockMutex == NULL) || (pArg->CreateMutex != NULL && pArg->DestroyMutex != NULL && pArg->LockMutex != NULL && pArg->UnlockMutex != NULL); if (!supplied_ok) { (void) pthread_mutex_unlock(&global_mutex); return (CKR_ARGUMENTS_BAD); } /* Check for a pReserved set */ if (pArg->pReserved != NULL) { free(Anchor); Anchor = NULL; (void) pthread_mutex_unlock(&global_mutex); return (CKR_ARGUMENTS_BAD); } /* * When the CKF_OS_LOCKING_OK flag isn't set and mutex * function pointers are supplied by an application, * return (an error. We must be able to use our own primitives. */ if (!(pArg->flags & CKF_OS_LOCKING_OK) && (pArg->CreateMutex != NULL)) { (void) pthread_mutex_unlock(&global_mutex); return (CKR_CANT_LOCK); } } (void) memset((char *)Anchor, 0, sizeof (API_Proc_Struct_t)); (void) pthread_mutex_init(&(Anchor->ProcMutex), NULL); (void) pthread_mutex_init(&(Anchor->SessListMutex), NULL); Anchor->Pid = getpid(); rv = ST_Initialize((void *)&FuncList, 0, NULL); (void) pthread_mutex_unlock(&global_mutex); return (rv); } CK_RV C_InitPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pPin, CK_ULONG ulPinLen) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) return (CKR_CRYPTOKI_NOT_INITIALIZED); if (! pPin && ulPinLen) return (CKR_ARGUMENTS_BAD); if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) return (CKR_SESSION_HANDLE_INVALID); if (rSession.slotID > NUMBER_SLOTS_MANAGED) return (CKR_SLOT_ID_INVALID); if (FuncList.ST_InitPIN) rv = FuncList.ST_InitPIN(rSession, pPin, ulPinLen); else rv = CKR_FUNCTION_NOT_SUPPORTED; return (rv); } CK_RV C_InitToken(CK_SLOT_ID slotID, CK_CHAR_PTR pPin, CK_ULONG ulPinLen, CK_CHAR_PTR pLabel) { CK_RV rv; if (API_Initialized() == FALSE) return (CKR_CRYPTOKI_NOT_INITIALIZED); if (! pPin && ulPinLen) return (CKR_ARGUMENTS_BAD); if (! pLabel) return (CKR_ARGUMENTS_BAD); if (!global_shm->token_available) return (CKR_SLOT_ID_INVALID); if (FuncList.ST_InitToken) rv = FuncList.ST_InitToken(slotID, pPin, ulPinLen, pLabel); else rv = CKR_FUNCTION_NOT_SUPPORTED; return (rv); } CK_RV C_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_CHAR_PTR pPin, CK_ULONG ulPinLen) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_Login) { rv = FuncList.ST_Login(rSession, userType, pPin, ulPinLen); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_Logout(CK_SESSION_HANDLE hSession) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_Logout) { rv = FuncList.ST_Logout(rSession); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } /*ARGSUSED*/ CK_RV C_OpenSession( CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication, CK_NOTIFY Notify, CK_SESSION_HANDLE_PTR phSession) { CK_RV rv; Session_Struct_t *apiSessp; if (API_Initialized() == FALSE) return (CKR_CRYPTOKI_NOT_INITIALIZED); if (!global_shm->token_available || (slotID > NUMBER_SLOTS_MANAGED)) return (CKR_SLOT_ID_INVALID); if (! phSession) return (CKR_FUNCTION_FAILED); if ((flags & CKF_SERIAL_SESSION) == 0) return (CKR_SESSION_PARALLEL_NOT_SUPPORTED); if ((apiSessp = (Session_Struct_t *)malloc( sizeof (Session_Struct_t))) == NULL) return (CKR_HOST_MEMORY); if (FuncList.ST_OpenSession) { rv = FuncList.ST_OpenSession(slotID, flags, &(apiSessp->RealHandle)); if (rv == CKR_OK) { *phSession = (CK_SESSION_HANDLE)apiSessp; apiSessp->SltId = slotID; AddToSessionList(apiSessp); } else { free(apiSessp); } } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, CK_ULONG ulSeedLen) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! pSeed && ulSeedLen) { return (CKR_ARGUMENTS_BAD); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_SeedRandom) { rv = FuncList.ST_SeedRandom(rSession, pSeed, ulSeedLen); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_SetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (! pTemplate) { return (CKR_TEMPLATE_INCOMPLETE); } if (! ulCount) { return (CKR_TEMPLATE_INCOMPLETE); } // Get local pointers to session if (FuncList.ST_SetAttributeValue) { rv = FuncList.ST_SetAttributeValue(rSession, hObject, pTemplate, ulCount); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_SetOperationState(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen, CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (! pOperationState || ulOperationStateLen == 0) { return (CKR_ARGUMENTS_BAD); } if (FuncList.ST_SetOperationState) { rv = FuncList.ST_SetOperationState(rSession, pOperationState, ulOperationStateLen, hEncryptionKey, hAuthenticationKey); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin, CK_ULONG ulOldLen, CK_CHAR_PTR pNewPin, CK_ULONG ulNewLen) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! pOldPin || ! pNewPin) return (CKR_PIN_INVALID); if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_SetPIN) { rv = FuncList.ST_SetPIN(rSession, pOldPin, ulOldLen, pNewPin, ulNewLen); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_Sign(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_Sign) { rv = FuncList.ST_Sign(rSession, pData, ulDataLen, pSignature, pulSignatureLen); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_SignEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! pPart || ! pulEncryptedPartLen) { return (CKR_ARGUMENTS_BAD); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_SignEncryptUpdate) { rv = FuncList.ST_SignEncryptUpdate(rSession, pPart, ulPartLen, pEncryptedPart, pulEncryptedPartLen); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! pulSignatureLen) { return (CKR_ARGUMENTS_BAD); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_SignFinal) { rv = FuncList.ST_SignFinal(rSession, pSignature, pulSignatureLen); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_SignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! pMechanism) { return (CKR_MECHANISM_INVALID); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_SignInit) { rv = FuncList.ST_SignInit(rSession, pMechanism, hKey); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_SignRecover) { rv = FuncList.ST_SignRecover(rSession, pData, ulDataLen, pSignature, pulSignatureLen); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_SignRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! pMechanism) { return (CKR_MECHANISM_INVALID); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_SignRecoverInit) { rv = FuncList.ST_SignRecoverInit(rSession, pMechanism, hKey); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_SignUpdate) { rv = FuncList.ST_SignUpdate(rSession, pPart, ulPartLen); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_UnwrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey, CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (!pMechanism) { return (CKR_MECHANISM_INVALID); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_UnwrapKey) { rv = FuncList.ST_UnwrapKey(rSession, pMechanism, hUnwrappingKey, pWrappedKey, ulWrappedKeyLen, pTemplate, ulAttributeCount, phKey); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_Verify) { rv = FuncList.ST_Verify(rSession, pData, ulDataLen, pSignature, ulSignatureLen); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_VerifyFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! pSignature) { return (CKR_ARGUMENTS_BAD); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_VerifyFinal) { rv = FuncList.ST_VerifyFinal(rSession, pSignature, ulSignatureLen); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_VerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! pMechanism) { return (CKR_MECHANISM_INVALID); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_VerifyInit) { rv = FuncList.ST_VerifyInit(rSession, pMechanism, hKey); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_VerifyRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_VerifyRecover) { rv = FuncList.ST_VerifyRecover(rSession, pSignature, ulSignatureLen, pData, pulDataLen); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_VerifyRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! pMechanism) { return (CKR_MECHANISM_INVALID); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_VerifyRecoverInit) { rv = FuncList.ST_VerifyRecoverInit(rSession, pMechanism, hKey); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } CK_RV C_VerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_VerifyUpdate) { rv = FuncList.ST_VerifyUpdate(rSession, pPart, ulPartLen); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } /*ARGSUSED*/ CK_RV C_WaitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, CK_VOID_PTR pReserved) { if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } return (CKR_FUNCTION_NOT_SUPPORTED); } CK_RV C_WrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey, CK_ULONG_PTR pulWrappedKeyLen) { CK_RV rv; ST_SESSION_T rSession; if (API_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (! pMechanism) { return (CKR_MECHANISM_INVALID); } if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { return (CKR_SESSION_HANDLE_INVALID); } if (FuncList.ST_WrapKey) { rv = FuncList.ST_WrapKey(rSession, pMechanism, hWrappingKey, hKey, pWrappedKey, pulWrappedKeyLen); } else { rv = CKR_FUNCTION_NOT_SUPPORTED; } return (rv); } #pragma init(api_init) #pragma fini(api_fini) static void api_init(void) { loginit(); if (! Initialized) { (void) pthread_atfork(tpmtoken_fork_prepare, tpmtoken_fork_parent, tpmtoken_fork_child); Initialized = 1; } } static void api_fini() { logterm(); if (API_Initialized() == TRUE) { (void) do_finalize(NULL); } } /* * Common Public License Version 0.5 * * THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF * THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, * REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES * RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. * * 1. DEFINITIONS * * "Contribution" means: * a) in the case of the initial Contributor, the * initial code and documentation distributed under * this Agreement, and * * b) in the case of each subsequent Contributor: * i) changes to the Program, and * ii) additions to the Program; * * where such changes and/or additions to the Program * originate from and are distributed by that * particular Contributor. A Contribution 'originates' * from a Contributor if it was added to the Program * by such Contributor itself or anyone acting on such * Contributor's behalf. Contributions do not include * additions to the Program which: (i) are separate * modules of software distributed in conjunction with * the Program under their own license agreement, and * (ii) are not derivative works of the Program. * * * "Contributor" means any person or entity that distributes * the Program. * * "Licensed Patents " mean patent claims licensable by a * Contributor which are necessarily infringed by the use or * sale of its Contribution alone or when combined with the * Program. * * "Program" means the Contributions distributed in * accordance with this Agreement. * * "Recipient" means anyone who receives the Program under * this Agreement, including all Contributors. * * 2. GRANT OF RIGHTS * * a) Subject to the terms of this Agreement, each * Contributor hereby grants Recipient a * no - exclusive, worldwide, royalt - free copyright * license to reproduce, prepare derivative works of, * publicly display, publicly perform, distribute and * sublicense the Contribution of such Contributor, if * any, and such derivative works, in source code and * object code form. * * b) Subject to the terms of this Agreement, each * Contributor hereby grants Recipient a * no - exclusive, worldwide, royalt - free patent * license under Licensed Patents to make, use, sell, * offer to sell, import and otherwise transfer the * Contribution of such Contributor, if any, in source * code and object code form. This patent license * shall apply to the combination of the Contribution * and the Program if, at the time the Contribution is * added by the Contributor, such addition of the * Contribution causes such combination to be covered * by the Licensed Patents. The patent license shall * not apply to any other combinations which include * the Contribution. No hardware per se is licensed * hereunder. * * c) Recipient understands that although each * Contributor grants the licenses to its * Contributions set forth herein, no assurances are * provided by any Contributor that the Program does * not infringe the patent or other intellectual * property rights of any other entity. Each * Contributor disclaims any liability to Recipient * for claims brought by any other entity based on * infringement of intellectual property rights or * otherwise. As a condition to exercising the rights * and licenses granted hereunder, each Recipient * hereby assumes sole responsibility to secure any * other intellectual property rights needed, if any. * * For example, if a third party patent license is * required to allow Recipient to distribute the * Program, it is Recipient's responsibility to * acquire that license before distributing the * Program. * * d) Each Contributor represents that to its * knowledge it has sufficient copyright rights in its * Contribution, if any, to grant the copyright * license set forth in this Agreement. * * 3. REQUIREMENTS * * A Contributor may choose to distribute the Program in * object code form under its own license agreement, provided * that: * a) it complies with the terms and conditions of * this Agreement; and * * b) its license agreement: * i) effectively disclaims on behalf of all * Contributors all warranties and conditions, express * and implied, including warranties or conditions of * title and no - infringement, and implied warranties * or conditions of merchantability and fitness for a * particular purpose; * * ii) effectively excludes on behalf of all * Contributors all liability for damages, including * direct, indirect, special, incidental and * consequential damages, such as lost profits; * * iii) states that any provisions which differ from * this Agreement are offered by that Contributor * alone and not by any other party; and * * iv) states that source code for the Program is * available from such Contributor, and informs * licensees how to obtain it in a reasonable manner * on or through a medium customarily used for * software exchange. * * When the Program is made available in source code form: * a) it must be made available under this Agreement; * and * b) a copy of this Agreement must be included with * each copy of the Program. * * Contributors may not remove or alter any copyright notices * contained within the Program. * * Each Contributor must identify itself as the originator of * its Contribution, if any, in a manner that reasonably * allows subsequent Recipients to identify the originator of * the Contribution. * * * 4. COMMERCIAL DISTRIBUTION * * Commercial distributors of software may accept certain * responsibilities with respect to end users, business * partners and the like. While this license is intended to * facilitate the commercial use of the Program, the * Contributor who includes the Program in a commercial * product offering should do so in a manner which does not * create potential liability for other Contributors. * Therefore, if a Contributor includes the Program in a * commercial product offering, such Contributor ("Commercial * Contributor") hereby agrees to defend and indemnify every * other Contributor ("Indemnified Contributor") against any * losses, damages and costs (collectively "Losses") arising * from claims, lawsuits and other legal actions brought by a * third party against the Indemnified Contributor to the * extent caused by the acts or omissions of such Commercial * Contributor in connection with its distribution of the * Program in a commercial product offering. The obligations * in this section do not apply to any claims or Losses * relating to any actual or alleged intellectual property * infringement. In order to qualify, an Indemnified * Contributor must: a) promptly notify the Commercial * Contributor in writing of such claim, and b) allow the * Commercial Contributor to control, and cooperate with the * Commercial Contributor in, the defense and any related * settlement negotiations. The Indemnified Contributor may * participate in any such claim at its own expense. * * * For example, a Contributor might include the Program in a * commercial product offering, Product X. That Contributor * is then a Commercial Contributor. If that Commercial * Contributor then makes performance claims, or offers * warranties related to Product X, those performance claims * and warranties are such Commercial Contributor's * responsibility alone. Under this section, the Commercial * Contributor would have to defend claims against the other * Contributors related to those performance claims and * warranties, and if a court requires any other Contributor * to pay any damages as a result, the Commercial Contributor * must pay those damages. * * * 5. NO WARRANTY * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE * PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR * IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR * CONDITIONS OF TITLE, NO - INFRINGEMENT, MERCHANTABILITY OR * FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely * responsible for determining the appropriateness of using * and distributing the Program and assumes all risks * associated with its exercise of rights under this * Agreement, including but not limited to the risks and * costs of program errors, compliance with applicable laws, * damage to or loss of data, programs or equipment, and * unavailability or interruption of operations. * * 6. DISCLAIMER OF LIABILITY * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER * RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION * LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE * OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * 7. GENERAL * * If any provision of this Agreement is invalid or * unenforceable under applicable law, it shall not affect * the validity or enforceability of the remainder of the * terms of this Agreement, and without further action by the * parties hereto, such provision shall be reformed to the * minimum extent necessary to make such provision valid and * enforceable. * * * If Recipient institutes patent litigation against a * Contributor with respect to a patent applicable to * software (including a cros - claim or counterclaim in a * lawsuit), then any patent licenses granted by that * Contributor to such Recipient under this Agreement shall * terminate as of the date such litigation is filed. In * addition, If Recipient institutes patent litigation * against any entity (including a cros - claim or * counterclaim in a lawsuit) alleging that the Program * itself (excluding combinations of the Program with other * software or hardware) infringes such Recipient's * patent(s), then such Recipient's rights granted under * Section 2(b) shall terminate as of the date such * litigation is filed. * * All Recipient's rights under this Agreement shall * terminate if it fails to comply with any of the material * terms or conditions of this Agreement and does not cure * such failure in a reasonable period of time after becoming * aware of such noncompliance. If all Recipient's rights * under this Agreement terminate, Recipient agrees to cease * use and distribution of the Program as soon as reasonably * practicable. However, Recipient's obligations under this * Agreement and any licenses granted by Recipient relating * to the Program shall continue and survive. * * Everyone is permitted to copy and distribute copies of * this Agreement, but in order to avoid inconsistency the * Agreement is copyrighted and may only be modified in the * following manner. The Agreement Steward reserves the right * to publish new versions (including revisions) of this * Agreement from time to time. No one other than the * Agreement Steward has the right to modify this Agreement. * * IBM is the initial Agreement Steward. IBM may assign the * responsibility to serve as the Agreement Steward to a * suitable separate entity. Each new version of the * Agreement will be given a distinguishing version number. * The Program (including Contributions) may always be * distributed subject to the version of the Agreement under * which it was received. In addition, after a new version of * the Agreement is published, Contributor may elect to * distribute the Program (including its Contributions) under * the new version. Except as expressly stated in Sections * 2(a) and 2(b) above, Recipient receives no rights or * licenses to the intellectual property of any Contributor * under this Agreement, whether expressly, by implication, * estoppel or otherwise. All rights in the Program not * expressly granted under this Agreement are reserved. * * * This Agreement is governed by the laws of the State of New * York and the intellectual property laws of the United * States of America. No party to this Agreement will bring a * legal action under this Agreement more than one year after * the cause of action arose. Each party waives its rights to * a jury trial in any resulting litigation. * * * * (C) COPYRIGHT International Business Machines Corp. 2001, 2002 */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * Copyright 2018 Gary Mills */ #include #include #include #include "tpmtok_int.h" extern API_Proc_Struct_t *Anchor; extern int logging; void logit(int, char *, ...); #ifdef DEBUG static int enabled = 0; #endif /* DEBUG */ void loginit() { #ifdef DEBUG if (!enabled) { enabled = 1; openlog("tpmtoken", LOG_PID | LOG_NDELAY, LOG_DAEMON); (void) setlogmask(LOG_UPTO(LOG_DEBUG)); logit(LOG_DEBUG, "Logging enabled %d enabled", enabled); } #endif /* DEBUG */ } void logterm() { #ifdef DEBUG closelog(); enabled = 0; #endif /* DEBUG */ } /*ARGSUSED*/ void logit(int type, char *fmt, ...) { #ifdef DEBUG va_list pvar; char buffer[BUFSIZ]; if (enabled) { if (type <= logging) { va_start(pvar, fmt); (void) vsnprintf(buffer, sizeof (buffer), fmt, pvar); va_end(pvar); syslog(type, buffer); } } #else return; #endif /* DEBUG */ } void AddToSessionList(Session_Struct_t *pSess) { Session_Struct_t *pCur; (void) pthread_mutex_lock(&(Anchor->SessListMutex)); pCur = Anchor->SessListBeg; if (! pCur) { (void) pthread_mutex_lock(&(Anchor->ProcMutex)); Anchor->SessListBeg = pSess; (void) pthread_mutex_unlock(&(Anchor->ProcMutex)); pSess->Previous = pSess->Next = NULL; } else { while (pCur->Next != NULL) { pCur = pCur->Next; } pCur->Next = pSess; pSess->Previous = pCur; pSess->Next = NULL; } (void) pthread_mutex_unlock(&(Anchor->SessListMutex)); } void RemoveFromSessionList(Session_Struct_t *pSess) { Session_Struct_t *pCur, *pTmp; (void) pthread_mutex_lock(&(Anchor->SessListMutex)); pCur = Anchor->SessListBeg; /* * Just in case check that there really is a list although * the call to ValidSession should have caught this already. * But someone may have removed the session already * while we were validating the call. */ if (pCur) { if (pCur == pSess) { (void) pthread_mutex_lock(&(Anchor->ProcMutex)); pTmp = pSess->Next; Anchor->SessListBeg = pSess->Next; if (pTmp) { pTmp->Previous = NULL; } free(pSess); (void) pthread_mutex_unlock(&(Anchor->ProcMutex)); pCur = NULL; } else { /* * First check for a Null element then check * next against the desired element. This will * allow the loop to terminate at the end of * the list even if the desired element is not in * the list (should not happen, but be defensive). */ while (pCur && pCur->Next != pSess) { pCur = pCur->Next; } /* * We did not hit the end of the list without finding * our element so we can continue to remove it */ if (pCur != NULL) { pTmp = pSess->Next; pCur->Next = pTmp; if (pTmp) { pTmp->Previous = pCur; } free(pSess); } } } (void) pthread_mutex_unlock(&(Anchor->SessListMutex)); } int Valid_Session(Session_Struct_t *pSession, ST_SESSION_T *rSession) { int rv = FALSE; Session_Struct_t *cSessionp; if (!pSession) return (FALSE); (void) pthread_mutex_lock(&(Anchor->SessListMutex)); cSessionp = Anchor->SessListBeg; while (cSessionp) { if (cSessionp == pSession) { rv = TRUE; rSession->sessionh = pSession->RealHandle; rSession->slotID = pSession->SltId; break; } cSessionp = (Session_Struct_t *)cSessionp->Next; } (void) pthread_mutex_unlock(&(Anchor->SessListMutex)); return (rv); } int API_Initialized() { return (Anchor != NULL && global_shm != NULL); } void Terminate_All_Process_Sessions() { CK_RV rv; logit(LOG_DEBUG, "Terminate_All_Process_Sessions"); rv = C_CloseAllSessions(TPM_SLOTID); /* * If the return (code is not OK, we are really hosed * since we are terminating the session. * For now we will just log it */ if (rv != CKR_OK) { logit(LOG_DEBUG, "Terminate_All_Process_Sessions RV %x", rv); } } /* * Common Public License Version 0.5 * * THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF * THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, * REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES * RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. * * 1. DEFINITIONS * * "Contribution" means: * a) in the case of the initial Contributor, the * initial code and documentation distributed under * this Agreement, and * * b) in the case of each subsequent Contributor: * i) changes to the Program, and * ii) additions to the Program; * * where such changes and/or additions to the Program * originate from and are distributed by that * particular Contributor. A Contribution 'originates' * from a Contributor if it was added to the Program * by such Contributor itself or anyone acting on such * Contributor's behalf. Contributions do not include * additions to the Program which: (i) are separate * modules of software distributed in conjunction with * the Program under their own license agreement, and * (ii) are not derivative works of the Program. * * * "Contributor" means any person or entity that distributes * the Program. * * "Licensed Patents " mean patent claims licensable by a * Contributor which are necessarily infringed by the use or * sale of its Contribution alone or when combined with the * Program. * * "Program" means the Contributions distributed in * accordance with this Agreement. * * "Recipient" means anyone who receives the Program under * this Agreement, including all Contributors. * * 2. GRANT OF RIGHTS * * a) Subject to the terms of this Agreement, each * Contributor hereby grants Recipient a * no - exclusive, worldwide, royalt - free copyright * license to reproduce, prepare derivative works of, * publicly display, publicly perform, distribute and * sublicense the Contribution of such Contributor, if * any, and such derivative works, in source code and * object code form. * * b) Subject to the terms of this Agreement, each * Contributor hereby grants Recipient a * no - exclusive, worldwide, royalt - free patent * license under Licensed Patents to make, use, sell, * offer to sell, import and otherwise transfer the * Contribution of such Contributor, if any, in source * code and object code form. This patent license * shall apply to the combination of the Contribution * and the Program if, at the time the Contribution is * added by the Contributor, such addition of the * Contribution causes such combination to be covered * by the Licensed Patents. The patent license shall * not apply to any other combinations which include * the Contribution. No hardware per se is licensed * hereunder. * * c) Recipient understands that although each * Contributor grants the licenses to its * Contributions set forth herein, no assurances are * provided by any Contributor that the Program does * not infringe the patent or other intellectual * property rights of any other entity. Each * Contributor disclaims any liability to Recipient * for claims brought by any other entity based on * infringement of intellectual property rights or * otherwise. As a condition to exercising the rights * and licenses granted hereunder, each Recipient * hereby assumes sole responsibility to secure any * other intellectual property rights needed, if any. * * For example, if a third party patent license is * required to allow Recipient to distribute the * Program, it is Recipient's responsibility to * acquire that license before distributing the * Program. * * d) Each Contributor represents that to its * knowledge it has sufficient copyright rights in its * Contribution, if any, to grant the copyright * license set forth in this Agreement. * * 3. REQUIREMENTS * * A Contributor may choose to distribute the Program in * object code form under its own license agreement, provided * that: * a) it complies with the terms and conditions of * this Agreement; and * * b) its license agreement: * i) effectively disclaims on behalf of all * Contributors all warranties and conditions, express * and implied, including warranties or conditions of * title and no - infringement, and implied warranties * or conditions of merchantability and fitness for a * particular purpose; * * ii) effectively excludes on behalf of all * Contributors all liability for damages, including * direct, indirect, special, incidental and * consequential damages, such as lost profits; * * iii) states that any provisions which differ from * this Agreement are offered by that Contributor * alone and not by any other party; and * * iv) states that source code for the Program is * available from such Contributor, and informs * licensees how to obtain it in a reasonable manner * on or through a medium customarily used for * software exchange. * * When the Program is made available in source code form: * a) it must be made available under this Agreement; * and * b) a copy of this Agreement must be included with * each copy of the Program. * * Contributors may not remove or alter any copyright notices * contained within the Program. * * Each Contributor must identify itself as the originator of * its Contribution, if any, in a manner that reasonably * allows subsequent Recipients to identify the originator of * the Contribution. * * * 4. COMMERCIAL DISTRIBUTION * * Commercial distributors of software may accept certain * responsibilities with respect to end users, business * partners and the like. While this license is intended to * facilitate the commercial use of the Program, the * Contributor who includes the Program in a commercial * product offering should do so in a manner which does not * create potential liability for other Contributors. * Therefore, if a Contributor includes the Program in a * commercial product offering, such Contributor ("Commercial * Contributor") hereby agrees to defend and indemnify every * other Contributor ("Indemnified Contributor") against any * losses, damages and costs (collectively "Losses") arising * from claims, lawsuits and other legal actions brought by a * third party against the Indemnified Contributor to the * extent caused by the acts or omissions of such Commercial * Contributor in connection with its distribution of the * Program in a commercial product offering. The obligations * in this section do not apply to any claims or Losses * relating to any actual or alleged intellectual property * infringement. In order to qualify, an Indemnified * Contributor must: a) promptly notify the Commercial * Contributor in writing of such claim, and b) allow the * Commercial Contributor to control, and cooperate with the * Commercial Contributor in, the defense and any related * settlement negotiations. The Indemnified Contributor may * participate in any such claim at its own expense. * * * For example, a Contributor might include the Program in a * commercial product offering, Product X. That Contributor * is then a Commercial Contributor. If that Commercial * Contributor then makes performance claims, or offers * warranties related to Product X, those performance claims * and warranties are such Commercial Contributor's * responsibility alone. Under this section, the Commercial * Contributor would have to defend claims against the other * Contributors related to those performance claims and * warranties, and if a court requires any other Contributor * to pay any damages as a result, the Commercial Contributor * must pay those damages. * * * 5. NO WARRANTY * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE * PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR * IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR * CONDITIONS OF TITLE, NO - INFRINGEMENT, MERCHANTABILITY OR * FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely * responsible for determining the appropriateness of using * and distributing the Program and assumes all risks * associated with its exercise of rights under this * Agreement, including but not limited to the risks and * costs of program errors, compliance with applicable laws, * damage to or loss of data, programs or equipment, and * unavailability or interruption of operations. * * 6. DISCLAIMER OF LIABILITY * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER * RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION * LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE * OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * 7. GENERAL * * If any provision of this Agreement is invalid or * unenforceable under applicable law, it shall not affect * the validity or enforceability of the remainder of the * terms of this Agreement, and without further action by the * parties hereto, such provision shall be reformed to the * minimum extent necessary to make such provision valid and * enforceable. * * * If Recipient institutes patent litigation against a * Contributor with respect to a patent applicable to * software (including a cros - claim or counterclaim in a * lawsuit), then any patent licenses granted by that * Contributor to such Recipient under this Agreement shall * terminate as of the date such litigation is filed. In * addition, If Recipient institutes patent litigation * against any entity (including a cros - claim or * counterclaim in a lawsuit) alleging that the Program * itself (excluding combinations of the Program with other * software or hardware) infringes such Recipient's * patent(s), then such Recipient's rights granted under * Section 2(b) shall terminate as of the date such * litigation is filed. * * All Recipient's rights under this Agreement shall * terminate if it fails to comply with any of the material * terms or conditions of this Agreement and does not cure * such failure in a reasonable period of time after becoming * aware of such noncompliance. If all Recipient's rights * under this Agreement terminate, Recipient agrees to cease * use and distribution of the Program as soon as reasonably * practicable. However, Recipient's obligations under this * Agreement and any licenses granted by Recipient relating * to the Program shall continue and survive. * * Everyone is permitted to copy and distribute copies of * this Agreement, but in order to avoid inconsistency the * Agreement is copyrighted and may only be modified in the * following manner. The Agreement Steward reserves the right * to publish new versions (including revisions) of this * Agreement from time to time. No one other than the * Agreement Steward has the right to modify this Agreement. * * IBM is the initial Agreement Steward. IBM may assign the * responsibility to serve as the Agreement Steward to a * suitable separate entity. Each new version of the * Agreement will be given a distinguishing version number. * The Program (including Contributions) may always be * distributed subject to the version of the Agreement under * which it was received. In addition, after a new version of * the Agreement is published, Contributor may elect to * distribute the Program (including its Contributions) under * the new version. Except as expressly stated in Sections * 2(a) and 2(b) above, Recipient receives no rights or * licenses to the intellectual property of any Contributor * under this Agreement, whether expressly, by implication, * estoppel or otherwise. All rights in the Program not * expressly granted under this Agreement are reserved. * * * This Agreement is governed by the laws of the State of New * York and the intellectual property laws of the United * States of America. No party to this Agreement will bring a * legal action under this Agreement more than one year after * the cause of action arose. Each party waives its rights to * a jury trial in any resulting litigation. * * * * (C) COPYRIGHT International Business Machines Corp. 2001, 2002 */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include "tpmtok_int.h" CK_ULONG ber_encode_INTEGER(CK_BBOOL length_only, CK_BYTE ** ber_int, CK_ULONG * ber_int_len, CK_BYTE * data, CK_ULONG data_len) { CK_BYTE *buf = NULL; CK_ULONG len; /* * if data_len < 127 use short form length id * if data_len < 256 use long form length id with * byte length field * if data_len < 65536 use long form length id with * byte length field * if data_len < 16777216 use long form length id * with byte length field */ if (data_len < 128) len = 1 + 1 + data_len; else if (data_len < 256) len = 1 + (1 + 1) + data_len; else if (data_len < (1 << 16)) len = 1 + (1 + 2) + data_len; else if (data_len < (1 << 24)) len = 1 + (1 + 3) + data_len; else return (CKR_FUNCTION_FAILED); if (length_only == TRUE) { *ber_int_len = len; return (CKR_OK); } buf = (CK_BYTE *)malloc(len); if (! buf) { return (CKR_HOST_MEMORY); } if (data_len < 128) { buf[0] = 0x02; buf[1] = data_len; (void) memcpy(&buf[2], data, data_len); *ber_int_len = len; *ber_int = buf; return (CKR_OK); } if (data_len < 256) { buf[0] = 0x02; buf[1] = 0x81; buf[2] = data_len; (void) memcpy(&buf[3], data, data_len); *ber_int_len = len; *ber_int = buf; return (CKR_OK); } if (data_len < (1 << 16)) { buf[0] = 0x02; buf[1] = 0x82; buf[2] = (data_len >> 8) & 0xFF; buf[3] = (data_len) & 0xFF; (void) memcpy(&buf[4], data, data_len); *ber_int_len = len; *ber_int = buf; return (CKR_OK); } if (data_len < (1 << 24)) { buf[0] = 0x02; buf[1] = 0x83; buf[2] = (data_len >> 16) & 0xFF; buf[3] = (data_len >> 8) & 0xFF; buf[4] = (data_len) & 0xFF; (void) memcpy(&buf[5], data, data_len); *ber_int_len = len; *ber_int = buf; return (CKR_OK); } free(buf); return (CKR_FUNCTION_FAILED); } CK_RV ber_decode_INTEGER(CK_BYTE * ber_int, CK_BYTE ** data, CK_ULONG * data_len, CK_ULONG * field_len) { CK_ULONG len, length_octets; if (! ber_int) { return (CKR_FUNCTION_FAILED); } if (ber_int[0] != 0x02) { return (CKR_FUNCTION_FAILED); } if ((ber_int[1] & 0x80) == 0) { len = ber_int[1] & 0x7F; *data = &ber_int[2]; *data_len = len; *field_len = 1 + 1 + len; return (CKR_OK); } length_octets = ber_int[1] & 0x7F; if (length_octets == 1) { len = ber_int[2]; *data = &ber_int[3]; *data_len = len; *field_len = 1 + (1 + 1) + len; return (CKR_OK); } if (length_octets == 2) { len = ber_int[2]; len = len << 8; len |= ber_int[3]; *data = &ber_int[4]; *data_len = len; *field_len = 1 + (1 + 2) + len; return (CKR_OK); } if (length_octets == 3) { len = ber_int[2]; len = len << 8; len |= ber_int[3]; len = len << 8; len |= ber_int[4]; *data = &ber_int[5]; *data_len = len; *field_len = 1 + (1 + 3) + len; return (CKR_OK); } return (CKR_FUNCTION_FAILED); } CK_RV ber_encode_OCTET_STRING(CK_BBOOL length_only, CK_BYTE ** str, CK_ULONG * str_len, CK_BYTE * data, CK_ULONG data_len) { CK_BYTE *buf = NULL; CK_ULONG len; /* * if data_len < 128 use shor - form length id * if data_len < 256 use lon - form length id with - byte length field * if data_len < 65536 use lon - form length id with - byte length field */ if (data_len < 128) len = 1 + 1 + data_len; else if (data_len < 256) len = 1 + (1 + 1) + data_len; else if (data_len < (1 << 16)) len = 1 + (1 + 2) + data_len; else if (data_len < (1 << 24)) len = 1 + (1 + 3) + data_len; else return (CKR_FUNCTION_FAILED); if (length_only == TRUE) { *str_len = len; return (CKR_OK); } buf = (CK_BYTE *)malloc(len); if (! buf) { return (CKR_HOST_MEMORY); } if (data_len < 128) { buf[0] = 0x04; /* primitive, OCTET STRING */ buf[1] = data_len; (void) memcpy(&buf[2], data, data_len); *str_len = len; *str = buf; return (CKR_OK); } if (data_len < 256) { buf[0] = 0x04; /* primitive, OCTET STRING */ buf[1] = 0x81; /* length header -- 1 length octets */ buf[2] = data_len; (void) memcpy(&buf[3], data, data_len); *str_len = len; *str = buf; return (CKR_OK); } if (data_len < (1 << 16)) { buf[0] = 0x04; /* primitive, OCTET STRING */ buf[1] = 0x82; /* length header -- 2 length octets */ buf[2] = (data_len >> 8) & 0xFF; buf[3] = (data_len) & 0xFF; (void) memcpy(&buf[4], data, data_len); *str_len = len; *str = buf; return (CKR_OK); } if (data_len < (1 << 24)) { buf[0] = 0x04; /* primitive, OCTET STRING */ buf[1] = 0x83; /* length header -- 3 length octets */ buf[2] = (data_len >> 16) & 0xFF; buf[3] = (data_len >> 8) & 0xFF; buf[4] = (data_len) & 0xFF; (void) memcpy(&buf[5], data, data_len); *str_len = len; *str = buf; return (CKR_OK); } free(buf); return (CKR_FUNCTION_FAILED); } CK_RV ber_decode_OCTET_STRING(CK_BYTE * str, CK_BYTE ** data, CK_ULONG * data_len, CK_ULONG * field_len) { CK_ULONG len, length_octets; if (! str) { return (CKR_FUNCTION_FAILED); } if (str[0] != 0x04) { return (CKR_FUNCTION_FAILED); } if ((str[1] & 0x80) == 0) { len = str[1] & 0x7F; *data = &str[2]; *data_len = len; *field_len = 1 + (1) + len; return (CKR_OK); } length_octets = str[1] & 0x7F; if (length_octets == 1) { len = str[2]; *data = &str[3]; *data_len = len; *field_len = 1 + (1 + 1) + len; return (CKR_OK); } if (length_octets == 2) { len = str[2]; len = len << 8; len |= str[3]; *data = &str[4]; *data_len = len; *field_len = 1 + (1 + 2) + len; return (CKR_OK); } if (length_octets == 3) { len = str[2]; len = len << 8; len |= str[3]; len = len << 8; len |= str[4]; *data = &str[5]; *data_len = len; *field_len = 1 + (1 + 3) + len; return (CKR_OK); } /* > 3 length octets implies a length > 16MB */ return (CKR_FUNCTION_FAILED); } CK_RV ber_encode_SEQUENCE(CK_BBOOL length_only, CK_BYTE ** seq, CK_ULONG * seq_len, CK_BYTE * data, CK_ULONG data_len) { CK_BYTE *buf = NULL; CK_ULONG len; if (data_len < 128) len = 1 + 1 + data_len; else if (data_len < 256) len = 1 + (1 + 1) + data_len; else if (data_len < (1 << 16)) len = 1 + (1 + 2) + data_len; else if (data_len < (1 << 24)) len = 1 + (1 + 3) + data_len; else return (CKR_FUNCTION_FAILED); if (length_only == TRUE) { *seq_len = len; return (CKR_OK); } buf = (CK_BYTE *)malloc(len); if (! buf) { return (CKR_HOST_MEMORY); } if (data_len < 128) { buf[0] = 0x30; /* constructed, SEQUENCE */ buf[1] = data_len; (void) memcpy(&buf[2], data, data_len); *seq_len = len; *seq = buf; return (CKR_OK); } if (data_len < 256) { buf[0] = 0x30; /* constructed, SEQUENCE */ buf[1] = 0x81; /* length header -- 1 length octets */ buf[2] = data_len; (void) memcpy(&buf[3], data, data_len); *seq_len = len; *seq = buf; return (CKR_OK); } if (data_len < (1 << 16)) { buf[0] = 0x30; /* constructed, SEQUENCE */ buf[1] = 0x82; /* length header -- 2 length octets */ buf[2] = (data_len >> 8) & 0xFF; buf[3] = (data_len) & 0xFF; (void) memcpy(&buf[4], data, data_len); *seq_len = len; *seq = buf; return (CKR_OK); } if (data_len < (1 << 24)) { buf[0] = 0x30; /* constructed, SEQUENCE */ buf[1] = 0x83; /* length header -- 3 length octets */ buf[2] = (data_len >> 16) & 0xFF; buf[3] = (data_len >> 8) & 0xFF; buf[4] = (data_len) & 0xFF; (void) memcpy(&buf[5], data, data_len); *seq_len = len; *seq = buf; return (CKR_OK); } return (CKR_FUNCTION_FAILED); } CK_RV ber_decode_SEQUENCE(CK_BYTE * seq, CK_BYTE ** data, CK_ULONG * data_len, CK_ULONG * field_len) { CK_ULONG len, length_octets; if (! seq) { return (CKR_FUNCTION_FAILED); } if (seq[0] != 0x30) { return (CKR_FUNCTION_FAILED); } if ((seq[1] & 0x80) == 0) { len = seq[1] & 0x7F; *data = &seq[2]; *data_len = len; *field_len = 1 + (1) + len; return (CKR_OK); } length_octets = seq[1] & 0x7F; if (length_octets == 1) { len = seq[2]; *data = &seq[3]; *data_len = len; *field_len = 1 + (1 + 1) + len; return (CKR_OK); } if (length_octets == 2) { len = seq[2]; len = len << 8; len |= seq[3]; *data = &seq[4]; *data_len = len; *field_len = 1 + (1 + 2) + len; return (CKR_OK); } if (length_octets == 3) { len = seq[2]; len = len << 8; len |= seq[3]; len = len << 8; len |= seq[4]; *data = &seq[5]; *data_len = len; *field_len = 1 + (1 + 3) + len; return (CKR_OK); } return (CKR_FUNCTION_FAILED); } /* * * PrivateKeyInfo ::= SEQUENCE { * version Version -- always '0' for now * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier * privateKey PrivateKey * attributes * } */ CK_RV ber_encode_PrivateKeyInfo(CK_BBOOL length_only, CK_BYTE ** data, CK_ULONG * data_len, CK_BYTE * algorithm_id, CK_ULONG algorithm_id_len, CK_BYTE * priv_key, CK_ULONG priv_key_len) { CK_BYTE * buf = NULL; CK_BYTE * tmp = NULL; CK_BYTE version[] = { 0 }; CK_BYTE attrib[] = { 0x05, 0x00 }; CK_ULONG len, total; CK_RV rc; len = 0; rc = ber_encode_INTEGER(TRUE, NULL, &total, version, sizeof (version)); if (rc != CKR_OK) { return (rc); } else len += total; len += algorithm_id_len; rc = ber_encode_OCTET_STRING(TRUE, NULL, &total, priv_key, priv_key_len); if (rc != CKR_OK) return (rc); len += total; /* for this stuff, attributes are always NULL == 05 00 */ len += sizeof (attrib); if (length_only == TRUE) { rc = ber_encode_SEQUENCE(TRUE, NULL, &total, NULL, len); if (rc == CKR_OK) *data_len = total; return (rc); } buf = (CK_BYTE *)malloc(len); if (! buf) { return (CKR_HOST_MEMORY); } len = 0; rc = ber_encode_INTEGER(FALSE, &tmp, &total, version, sizeof (version)); if (rc != CKR_OK) { goto error; } (void) memcpy(buf + len, tmp, total); len += total; free(tmp); (void) memcpy(buf + len, algorithm_id, algorithm_id_len); len += algorithm_id_len; rc = ber_encode_OCTET_STRING(FALSE, &tmp, &total, priv_key, priv_key_len); if (rc != CKR_OK) { goto error; } (void) memcpy(buf + len, tmp, total); len += total; free(tmp); (void) memcpy(buf + len, attrib, sizeof (attrib)); len += sizeof (attrib); rc = ber_encode_SEQUENCE(FALSE, data, data_len, buf, len); error: free(buf); return (rc); } CK_RV ber_decode_PrivateKeyInfo(CK_BYTE * data, CK_ULONG data_len, CK_BYTE ** algorithm, CK_ULONG * alg_len, CK_BYTE ** priv_key) { CK_BYTE *buf = NULL; CK_BYTE *alg = NULL; CK_BYTE *ver = NULL; CK_ULONG buf_len, offset, len, field_len; CK_RV rc; if (! data || (data_len == 0)) { return (CKR_FUNCTION_FAILED); } rc = ber_decode_SEQUENCE(data, &buf, &buf_len, &field_len); if (rc != CKR_OK) { return (rc); } offset = 0; rc = ber_decode_INTEGER(buf + offset, &ver, &len, &field_len); if (rc != CKR_OK) { return (rc); } offset += field_len; rc = ber_decode_SEQUENCE(buf + offset, &alg, &len, &field_len); if (rc != CKR_OK) { return (rc); } *algorithm = alg; *alg_len = len; rc = ber_decode_OCTET_STRING(alg + len, priv_key, &buf_len, &field_len); return (rc); } /* * RSAPrivateKey ::= SEQUENCE { * version Version -- always '0' for now * modulus INTEGER * publicExponent INTEGER * privateExponent INTEGER * prime1 INTEGER * prime2 INTEGER * exponent1 INTEGER * exponent2 INTEGER * coefficient INTEGER * } */ CK_RV ber_encode_RSAPrivateKey(CK_BBOOL length_only, CK_BYTE ** data, CK_ULONG * data_len, CK_ATTRIBUTE * modulus, CK_ATTRIBUTE * publ_exp, CK_ATTRIBUTE * priv_exp, CK_ATTRIBUTE * prime1, CK_ATTRIBUTE * prime2, CK_ATTRIBUTE * exponent1, CK_ATTRIBUTE * exponent2, CK_ATTRIBUTE * coeff) { CK_BYTE *buf = NULL; CK_BYTE *buf2 = NULL; CK_ULONG len, offset; CK_BYTE version[] = { 0 }; CK_RV rc; offset = 0; rc = 0; rc |= ber_encode_INTEGER(TRUE, NULL, &len, NULL, sizeof (version)); offset += len; rc |= ber_encode_INTEGER(TRUE, NULL, &len, NULL, modulus->ulValueLen); offset += len; rc |= ber_encode_INTEGER(TRUE, NULL, &len, NULL, publ_exp->ulValueLen); offset += len; rc |= ber_encode_INTEGER(TRUE, NULL, &len, NULL, priv_exp->ulValueLen); offset += len; rc |= ber_encode_INTEGER(TRUE, NULL, &len, NULL, prime1->ulValueLen); offset += len; rc |= ber_encode_INTEGER(TRUE, NULL, &len, NULL, prime2->ulValueLen); offset += len; rc |= ber_encode_INTEGER(TRUE, NULL, &len, NULL, exponent1->ulValueLen); offset += len; rc |= ber_encode_INTEGER(TRUE, NULL, &len, NULL, exponent2->ulValueLen); offset += len; rc |= ber_encode_INTEGER(TRUE, NULL, &len, NULL, coeff->ulValueLen); offset += len; if (rc != CKR_OK) { return (CKR_FUNCTION_FAILED); } if (length_only == TRUE) { rc = ber_encode_SEQUENCE(TRUE, NULL, &len, NULL, offset); if (rc != CKR_OK) return (rc); rc = ber_encode_PrivateKeyInfo(TRUE, NULL, data_len, NULL, ber_AlgIdRSAEncryptionLen, NULL, len); if (rc != CKR_OK) return (rc); return (rc); } buf = (CK_BYTE *)malloc(offset); if (! buf) { return (CKR_HOST_MEMORY); } offset = 0; rc = 0; rc = ber_encode_INTEGER(FALSE, &buf2, &len, version, sizeof (version)); if (rc != CKR_OK) { goto error; } (void) memcpy(buf + offset, buf2, len); offset += len; free(buf2); rc = ber_encode_INTEGER(FALSE, &buf2, &len, (CK_BYTE *)modulus + sizeof (CK_ATTRIBUTE), modulus->ulValueLen); if (rc != CKR_OK) { goto error; } (void) memcpy(buf + offset, buf2, len); offset += len; free(buf2); rc = ber_encode_INTEGER(FALSE, &buf2, &len, (CK_BYTE *)publ_exp + sizeof (CK_ATTRIBUTE), publ_exp->ulValueLen); if (rc != CKR_OK) { goto error; } (void) memcpy(buf + offset, buf2, len); offset += len; free(buf2); rc = ber_encode_INTEGER(FALSE, &buf2, &len, (CK_BYTE *)priv_exp + sizeof (CK_ATTRIBUTE), priv_exp->ulValueLen); if (rc != CKR_OK) { goto error; } (void) memcpy(buf + offset, buf2, len); offset += len; free(buf2); rc = ber_encode_INTEGER(FALSE, &buf2, &len, (CK_BYTE *)prime1 + sizeof (CK_ATTRIBUTE), prime1->ulValueLen); if (rc != CKR_OK) { goto error; } (void) memcpy(buf + offset, buf2, len); offset += len; free(buf2); rc = ber_encode_INTEGER(FALSE, &buf2, &len, (CK_BYTE *)prime2 + sizeof (CK_ATTRIBUTE), prime2->ulValueLen); if (rc != CKR_OK) { goto error; } (void) memcpy(buf + offset, buf2, len); offset += len; free(buf2); rc = ber_encode_INTEGER(FALSE, &buf2, &len, (CK_BYTE *)exponent1 + sizeof (CK_ATTRIBUTE), exponent1->ulValueLen); if (rc != CKR_OK) { goto error; } (void) memcpy(buf + offset, buf2, len); offset += len; free(buf2); rc = ber_encode_INTEGER(FALSE, &buf2, &len, (CK_BYTE *)exponent2 + sizeof (CK_ATTRIBUTE), exponent2->ulValueLen); if (rc != CKR_OK) { goto error; } (void) memcpy(buf + offset, buf2, len); offset += len; free(buf2); rc = ber_encode_INTEGER(FALSE, &buf2, &len, (CK_BYTE *)coeff + sizeof (CK_ATTRIBUTE), coeff->ulValueLen); if (rc != CKR_OK) { goto error; } (void) memcpy(buf + offset, buf2, len); offset += len; free(buf2); rc = ber_encode_SEQUENCE(FALSE, &buf2, &len, buf, offset); if (rc != CKR_OK) { goto error; } rc = ber_encode_PrivateKeyInfo(FALSE, data, data_len, ber_AlgIdRSAEncryption, ber_AlgIdRSAEncryptionLen, buf2, len); error: if (buf2) free(buf2); if (buf) free(buf); return (rc); } CK_RV ber_decode_RSAPrivateKey(CK_BYTE * data, CK_ULONG data_len, CK_ATTRIBUTE ** modulus, CK_ATTRIBUTE ** publ_exp, CK_ATTRIBUTE ** priv_exp, CK_ATTRIBUTE ** prime1, CK_ATTRIBUTE ** prime2, CK_ATTRIBUTE ** exponent1, CK_ATTRIBUTE ** exponent2, CK_ATTRIBUTE ** coeff) { CK_ATTRIBUTE *n_attr = NULL; CK_ATTRIBUTE *e_attr = NULL; CK_ATTRIBUTE *d_attr = NULL; CK_ATTRIBUTE *p_attr = NULL; CK_ATTRIBUTE *q_attr = NULL; CK_ATTRIBUTE *e1_attr = NULL; CK_ATTRIBUTE *e2_attr = NULL; CK_ATTRIBUTE *coeff_attr = NULL; CK_BYTE *alg = NULL; CK_BYTE *rsa_priv_key = NULL; CK_BYTE *buf = NULL; CK_BYTE *tmp = NULL; CK_ULONG offset, buf_len, field_len, len; CK_RV rc; rc = ber_decode_PrivateKeyInfo(data, data_len, &alg, &len, &rsa_priv_key); if (rc != CKR_OK) { return (rc); } if (memcmp(alg, ber_rsaEncryption, ber_rsaEncryptionLen) != 0) { return (CKR_FUNCTION_FAILED); } rc = ber_decode_SEQUENCE(rsa_priv_key, &buf, &buf_len, &field_len); if (rc != CKR_OK) return (rc); offset = 0; rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); if (rc != CKR_OK) { goto cleanup; } offset += field_len; rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); if (rc != CKR_OK) { goto cleanup; } offset += field_len; rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); if (rc != CKR_OK) { goto cleanup; } offset += field_len; rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); if (rc != CKR_OK) { goto cleanup; } offset += field_len; rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); if (rc != CKR_OK) { goto cleanup; } offset += field_len; rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); if (rc != CKR_OK) { goto cleanup; } offset += field_len; rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); if (rc != CKR_OK) { goto cleanup; } offset += field_len; rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); if (rc != CKR_OK) { goto cleanup; } offset += field_len; rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); if (rc != CKR_OK) { goto cleanup; } offset += field_len; if (offset > buf_len) { return (CKR_FUNCTION_FAILED); } offset = 0; rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); if (rc != CKR_OK) { goto cleanup; } offset += field_len; rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); if (rc != CKR_OK) { goto cleanup; } else { rc = build_attribute(CKA_MODULUS, tmp, len, &n_attr); if (rc != CKR_OK) { goto cleanup; } offset += field_len; } rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); if (rc != CKR_OK) { goto cleanup; } else { rc = build_attribute(CKA_PUBLIC_EXPONENT, tmp, len, &e_attr); if (rc != CKR_OK) { goto cleanup; } offset += field_len; } rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); if (rc != CKR_OK) { goto cleanup; } else { rc = build_attribute(CKA_PRIVATE_EXPONENT, tmp, len, &d_attr); if (rc != CKR_OK) { goto cleanup; } offset += field_len; } rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); if (rc != CKR_OK) { goto cleanup; } else { rc = build_attribute(CKA_PRIME_1, tmp, len, &p_attr); if (rc != CKR_OK) { goto cleanup; } offset += field_len; } rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); if (rc != CKR_OK) { goto cleanup; } else { rc = build_attribute(CKA_PRIME_2, tmp, len, &q_attr); if (rc != CKR_OK) { goto cleanup; } offset += field_len; } rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); if (rc != CKR_OK) { goto cleanup; } else { rc = build_attribute(CKA_EXPONENT_1, tmp, len, &e1_attr); if (rc != CKR_OK) { goto cleanup; } offset += field_len; } rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); if (rc != CKR_OK) { goto cleanup; } else { rc = build_attribute(CKA_EXPONENT_2, tmp, len, &e2_attr); if (rc != CKR_OK) { goto cleanup; } offset += field_len; } rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len); if (rc != CKR_OK) { goto cleanup; } else { rc = build_attribute(CKA_COEFFICIENT, tmp, len, &coeff_attr); if (rc != CKR_OK) { goto cleanup; } offset += len; } *modulus = n_attr; *publ_exp = e_attr; *priv_exp = d_attr; *prime1 = p_attr; *prime2 = q_attr; *exponent1 = e1_attr; *exponent2 = e2_attr; *coeff = coeff_attr; return (CKR_OK); cleanup: if (n_attr) free(n_attr); if (e_attr) free(e_attr); if (d_attr) free(d_attr); if (p_attr) free(p_attr); if (q_attr) free(q_attr); if (e1_attr) free(e1_attr); if (e2_attr) free(e2_attr); if (coeff_attr) free(coeff_attr); return (rc); } /* * Common Public License Version 0.5 * * THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF * THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, * REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES * RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. * * 1. DEFINITIONS * * "Contribution" means: * a) in the case of the initial Contributor, the * initial code and documentation distributed under * this Agreement, and * * b) in the case of each subsequent Contributor: * i) changes to the Program, and * ii) additions to the Program; * * where such changes and/or additions to the Program * originate from and are distributed by that * particular Contributor. A Contribution 'originates' * from a Contributor if it was added to the Program * by such Contributor itself or anyone acting on such * Contributor's behalf. Contributions do not include * additions to the Program which: (i) are separate * modules of software distributed in conjunction with * the Program under their own license agreement, and * (ii) are not derivative works of the Program. * * * "Contributor" means any person or entity that distributes * the Program. * * "Licensed Patents " mean patent claims licensable by a * Contributor which are necessarily infringed by the use or * sale of its Contribution alone or when combined with the * Program. * * "Program" means the Contributions distributed in * accordance with this Agreement. * * "Recipient" means anyone who receives the Program under * this Agreement, including all Contributors. * * 2. GRANT OF RIGHTS * * a) Subject to the terms of this Agreement, each * Contributor hereby grants Recipient a * no - exclusive, worldwide, royalt - free copyright * license to reproduce, prepare derivative works of, * publicly display, publicly perform, distribute and * sublicense the Contribution of such Contributor, if * any, and such derivative works, in source code and * object code form. * * b) Subject to the terms of this Agreement, each * Contributor hereby grants Recipient a * no - exclusive, worldwide, royalt - free patent * license under Licensed Patents to make, use, sell, * offer to sell, import and otherwise transfer the * Contribution of such Contributor, if any, in source * code and object code form. This patent license * shall apply to the combination of the Contribution * and the Program if, at the time the Contribution is * added by the Contributor, such addition of the * Contribution causes such combination to be covered * by the Licensed Patents. The patent license shall * not apply to any other combinations which include * the Contribution. No hardware per se is licensed * hereunder. * * c) Recipient understands that although each * Contributor grants the licenses to its * Contributions set forth herein, no assurances are * provided by any Contributor that the Program does * not infringe the patent or other intellectual * property rights of any other entity. Each * Contributor disclaims any liability to Recipient * for claims brought by any other entity based on * infringement of intellectual property rights or * otherwise. As a condition to exercising the rights * and licenses granted hereunder, each Recipient * hereby assumes sole responsibility to secure any * other intellectual property rights needed, if any. * * For example, if a third party patent license is * required to allow Recipient to distribute the * Program, it is Recipient's responsibility to * acquire that license before distributing the * Program. * * d) Each Contributor represents that to its * knowledge it has sufficient copyright rights in its * Contribution, if any, to grant the copyright * license set forth in this Agreement. * * 3. REQUIREMENTS * * A Contributor may choose to distribute the Program in * object code form under its own license agreement, provided * that: * a) it complies with the terms and conditions of * this Agreement; and * * b) its license agreement: * i) effectively disclaims on behalf of all * Contributors all warranties and conditions, express * and implied, including warranties or conditions of * title and no - infringement, and implied warranties * or conditions of merchantability and fitness for a * particular purpose; * * ii) effectively excludes on behalf of all * Contributors all liability for damages, including * direct, indirect, special, incidental and * consequential damages, such as lost profits; * * iii) states that any provisions which differ from * this Agreement are offered by that Contributor * alone and not by any other party; and * * iv) states that source code for the Program is * available from such Contributor, and informs * licensees how to obtain it in a reasonable manner * on or through a medium customarily used for * software exchange. * * When the Program is made available in source code form: * a) it must be made available under this Agreement; * and * b) a copy of this Agreement must be included with * each copy of the Program. * * Contributors may not remove or alter any copyright notices * contained within the Program. * * Each Contributor must identify itself as the originator of * its Contribution, if any, in a manner that reasonably * allows subsequent Recipients to identify the originator of * the Contribution. * * * 4. COMMERCIAL DISTRIBUTION * * Commercial distributors of software may accept certain * responsibilities with respect to end users, business * partners and the like. While this license is intended to * facilitate the commercial use of the Program, the * Contributor who includes the Program in a commercial * product offering should do so in a manner which does not * create potential liability for other Contributors. * Therefore, if a Contributor includes the Program in a * commercial product offering, such Contributor ("Commercial * Contributor") hereby agrees to defend and indemnify every * other Contributor ("Indemnified Contributor") against any * losses, damages and costs (collectively "Losses") arising * from claims, lawsuits and other legal actions brought by a * third party against the Indemnified Contributor to the * extent caused by the acts or omissions of such Commercial * Contributor in connection with its distribution of the * Program in a commercial product offering. The obligations * in this section do not apply to any claims or Losses * relating to any actual or alleged intellectual property * infringement. In order to qualify, an Indemnified * Contributor must: a) promptly notify the Commercial * Contributor in writing of such claim, and b) allow the * Commercial Contributor to control, and cooperate with the * Commercial Contributor in, the defense and any related * settlement negotiations. The Indemnified Contributor may * participate in any such claim at its own expense. * * * For example, a Contributor might include the Program in a * commercial product offering, Product X. That Contributor * is then a Commercial Contributor. If that Commercial * Contributor then makes performance claims, or offers * warranties related to Product X, those performance claims * and warranties are such Commercial Contributor's * responsibility alone. Under this section, the Commercial * Contributor would have to defend claims against the other * Contributors related to those performance claims and * warranties, and if a court requires any other Contributor * to pay any damages as a result, the Commercial Contributor * must pay those damages. * * * 5. NO WARRANTY * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE * PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR * IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR * CONDITIONS OF TITLE, NO - INFRINGEMENT, MERCHANTABILITY OR * FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely * responsible for determining the appropriateness of using * and distributing the Program and assumes all risks * associated with its exercise of rights under this * Agreement, including but not limited to the risks and * costs of program errors, compliance with applicable laws, * damage to or loss of data, programs or equipment, and * unavailability or interruption of operations. * * 6. DISCLAIMER OF LIABILITY * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER * RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION * LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE * OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * 7. GENERAL * * If any provision of this Agreement is invalid or * unenforceable under applicable law, it shall not affect * the validity or enforceability of the remainder of the * terms of this Agreement, and without further action by the * parties hereto, such provision shall be reformed to the * minimum extent necessary to make such provision valid and * enforceable. * * * If Recipient institutes patent litigation against a * Contributor with respect to a patent applicable to * software (including a cros - claim or counterclaim in a * lawsuit), then any patent licenses granted by that * Contributor to such Recipient under this Agreement shall * terminate as of the date such litigation is filed. In * addition, If Recipient institutes patent litigation * against any entity (including a cros - claim or * counterclaim in a lawsuit) alleging that the Program * itself (excluding combinations of the Program with other * software or hardware) infringes such Recipient's * patent(s), then such Recipient's rights granted under * Section 2(b) shall terminate as of the date such * litigation is filed. * * All Recipient's rights under this Agreement shall * terminate if it fails to comply with any of the material * terms or conditions of this Agreement and does not cure * such failure in a reasonable period of time after becoming * aware of such noncompliance. If all Recipient's rights * under this Agreement terminate, Recipient agrees to cease * use and distribution of the Program as soon as reasonably * practicable. However, Recipient's obligations under this * Agreement and any licenses granted by Recipient relating * to the Program shall continue and survive. * * Everyone is permitted to copy and distribute copies of * this Agreement, but in order to avoid inconsistency the * Agreement is copyrighted and may only be modified in the * following manner. The Agreement Steward reserves the right * to publish new versions (including revisions) of this * Agreement from time to time. No one other than the * Agreement Steward has the right to modify this Agreement. * * IBM is the initial Agreement Steward. IBM may assign the * responsibility to serve as the Agreement Steward to a * suitable separate entity. Each new version of the * Agreement will be given a distinguishing version number. * The Program (including Contributions) may always be * distributed subject to the version of the Agreement under * which it was received. In addition, after a new version of * the Agreement is published, Contributor may elect to * distribute the Program (including its Contributions) under * the new version. Except as expressly stated in Sections * 2(a) and 2(b) above, Recipient receives no rights or * licenses to the intellectual property of any Contributor * under this Agreement, whether expressly, by implication, * estoppel or otherwise. All rights in the Program not * expressly granted under this Agreement are reserved. * * * This Agreement is governed by the laws of the State of New * York and the intellectual property laws of the United * States of America. No party to this Agreement will bring a * legal action under this Agreement more than one year after * the cause of action arose. Each party waives its rights to * a jury trial in any resulting litigation. * * * * (C) COPYRIGHT International Business Machines Corp. 2001, 2002 */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * Copyright 2012 Milan Jurik. All rights reserved. */ #include "tpmtok_int.h" /* * cert_check_required_attributes * * Checks for required attributes for generic CKO_CERTIFICATE objects * * CKA_CERTIFICATE_TYPE : must be present on MODE_CREATE. */ static CK_RV cert_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode) { CK_ATTRIBUTE * attr = NULL; CK_BBOOL found; if (! tmpl) return (CKR_FUNCTION_FAILED); if (mode == MODE_CREATE) { found = template_attribute_find(tmpl, CKA_CERTIFICATE_TYPE, &attr); if (found == FALSE) { return (CKR_TEMPLATE_INCOMPLETE); } } return (template_check_required_base_attributes(tmpl, mode)); } /* * cert_validate_attribute() */ CK_RV cert_validate_attribute(TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode) { CK_CERTIFICATE_TYPE type; switch (attr->type) { case CKA_CERTIFICATE_TYPE: if (mode != MODE_CREATE) { return (CKR_ATTRIBUTE_READ_ONLY); } type = *(CK_CERTIFICATE_TYPE *)attr->pValue; if (type == CKC_X_509 || type >= CKC_VENDOR_DEFINED) return (CKR_OK); else { return (CKR_ATTRIBUTE_VALUE_INVALID); } default: return ( template_validate_base_attribute(tmpl, attr, mode)); } } CK_RV cert_x509_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL found; found = template_attribute_find(tmpl, CKA_SUBJECT, &attr); if (! found) { return (CKR_TEMPLATE_INCOMPLETE); } found = template_attribute_find(tmpl, CKA_VALUE, &attr); if (! found) { return (CKR_TEMPLATE_INCOMPLETE); } return (cert_check_required_attributes(tmpl, mode)); } /* * cert_x509_set_default_attributes() * * Set the default attributes for X.509 certificates * * CKA_ID : empty string * CKA_ISSUER : empty string * CKA_SERIAL_NUMBER : empty string */ CK_RV cert_x509_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode) { CK_ATTRIBUTE * id_attr = NULL; CK_ATTRIBUTE * issuer_attr = NULL; CK_ATTRIBUTE * serial_attr = NULL; if (mode) id_attr = NULL; id_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE)); issuer_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE)); serial_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE)); if (! id_attr || ! issuer_attr || ! serial_attr) { if (id_attr) free(id_attr); if (issuer_attr) free(issuer_attr); if (serial_attr) free(serial_attr); return (CKR_HOST_MEMORY); } id_attr->type = CKA_ID; id_attr->ulValueLen = 0; id_attr->pValue = NULL; issuer_attr->type = CKA_ISSUER; issuer_attr->ulValueLen = 0; issuer_attr->pValue = NULL; serial_attr->type = CKA_SERIAL_NUMBER; serial_attr->ulValueLen = 0; serial_attr->pValue = NULL; (void) template_update_attribute(tmpl, id_attr); (void) template_update_attribute(tmpl, issuer_attr); (void) template_update_attribute(tmpl, serial_attr); return (CKR_OK); } CK_RV cert_x509_validate_attribute(TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode) { switch (attr->type) { case CKA_SUBJECT: if (mode != MODE_CREATE) return (CKR_ATTRIBUTE_READ_ONLY); else return (CKR_OK); case CKA_ID: case CKA_ISSUER: case CKA_SERIAL_NUMBER: return (CKR_OK); case CKA_VALUE: if (mode != MODE_CREATE) return (CKR_ATTRIBUTE_READ_ONLY); else return (CKR_OK); default: return (cert_validate_attribute(tmpl, attr, mode)); } } CK_RV cert_vendor_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode) { return (cert_check_required_attributes(tmpl, mode)); } CK_RV cert_vendor_validate_attribute(TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode) { return (cert_validate_attribute(tmpl, attr, mode)); } /* * Common Public License Version 0.5 * * THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF * THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, * REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES * RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. * * 1. DEFINITIONS * * "Contribution" means: * a) in the case of the initial Contributor, the * initial code and documentation distributed under * this Agreement, and * * b) in the case of each subsequent Contributor: * i) changes to the Program, and * ii) additions to the Program; * * where such changes and/or additions to the Program * originate from and are distributed by that * particular Contributor. A Contribution 'originates' * from a Contributor if it was added to the Program * by such Contributor itself or anyone acting on such * Contributor's behalf. Contributions do not include * additions to the Program which: (i) are separate * modules of software distributed in conjunction with * the Program under their own license agreement, and * (ii) are not derivative works of the Program. * * * "Contributor" means any person or entity that distributes * the Program. * * "Licensed Patents " mean patent claims licensable by a * Contributor which are necessarily infringed by the use or * sale of its Contribution alone or when combined with the * Program. * * "Program" means the Contributions distributed in * accordance with this Agreement. * * "Recipient" means anyone who receives the Program under * this Agreement, including all Contributors. * * 2. GRANT OF RIGHTS * * a) Subject to the terms of this Agreement, each * Contributor hereby grants Recipient a * no - exclusive, worldwide, royalt - free copyright * license to reproduce, prepare derivative works of, * publicly display, publicly perform, distribute and * sublicense the Contribution of such Contributor, if * any, and such derivative works, in source code and * object code form. * * b) Subject to the terms of this Agreement, each * Contributor hereby grants Recipient a * no - exclusive, worldwide, royalt - free patent * license under Licensed Patents to make, use, sell, * offer to sell, import and otherwise transfer the * Contribution of such Contributor, if any, in source * code and object code form. This patent license * shall apply to the combination of the Contribution * and the Program if, at the time the Contribution is * added by the Contributor, such addition of the * Contribution causes such combination to be covered * by the Licensed Patents. The patent license shall * not apply to any other combinations which include * the Contribution. No hardware per se is licensed * hereunder. * * c) Recipient understands that although each * Contributor grants the licenses to its * Contributions set forth herein, no assurances are * provided by any Contributor that the Program does * not infringe the patent or other intellectual * property rights of any other entity. Each * Contributor disclaims any liability to Recipient * for claims brought by any other entity based on * infringement of intellectual property rights or * otherwise. As a condition to exercising the rights * and licenses granted hereunder, each Recipient * hereby assumes sole responsibility to secure any * other intellectual property rights needed, if any. * * For example, if a third party patent license is * required to allow Recipient to distribute the * Program, it is Recipient's responsibility to * acquire that license before distributing the * Program. * * d) Each Contributor represents that to its * knowledge it has sufficient copyright rights in its * Contribution, if any, to grant the copyright * license set forth in this Agreement. * * 3. REQUIREMENTS * * A Contributor may choose to distribute the Program in * object code form under its own license agreement, provided * that: * a) it complies with the terms and conditions of * this Agreement; and * * b) its license agreement: * i) effectively disclaims on behalf of all * Contributors all warranties and conditions, express * and implied, including warranties or conditions of * title and no - infringement, and implied warranties * or conditions of merchantability and fitness for a * particular purpose; * * ii) effectively excludes on behalf of all * Contributors all liability for damages, including * direct, indirect, special, incidental and * consequential damages, such as lost profits; * * iii) states that any provisions which differ from * this Agreement are offered by that Contributor * alone and not by any other party; and * * iv) states that source code for the Program is * available from such Contributor, and informs * licensees how to obtain it in a reasonable manner * on or through a medium customarily used for * software exchange. * * When the Program is made available in source code form: * a) it must be made available under this Agreement; * and * b) a copy of this Agreement must be included with * each copy of the Program. * * Contributors may not remove or alter any copyright notices * contained within the Program. * * Each Contributor must identify itself as the originator of * its Contribution, if any, in a manner that reasonably * allows subsequent Recipients to identify the originator of * the Contribution. * * * 4. COMMERCIAL DISTRIBUTION * * Commercial distributors of software may accept certain * responsibilities with respect to end users, business * partners and the like. While this license is intended to * facilitate the commercial use of the Program, the * Contributor who includes the Program in a commercial * product offering should do so in a manner which does not * create potential liability for other Contributors. * Therefore, if a Contributor includes the Program in a * commercial product offering, such Contributor ("Commercial * Contributor") hereby agrees to defend and indemnify every * other Contributor ("Indemnified Contributor") against any * losses, damages and costs (collectively "Losses") arising * from claims, lawsuits and other legal actions brought by a * third party against the Indemnified Contributor to the * extent caused by the acts or omissions of such Commercial * Contributor in connection with its distribution of the * Program in a commercial product offering. The obligations * in this section do not apply to any claims or Losses * relating to any actual or alleged intellectual property * infringement. In order to qualify, an Indemnified * Contributor must: a) promptly notify the Commercial * Contributor in writing of such claim, and b) allow the * Commercial Contributor to control, and cooperate with the * Commercial Contributor in, the defense and any related * settlement negotiations. The Indemnified Contributor may * participate in any such claim at its own expense. * * * For example, a Contributor might include the Program in a * commercial product offering, Product X. That Contributor * is then a Commercial Contributor. If that Commercial * Contributor then makes performance claims, or offers * warranties related to Product X, those performance claims * and warranties are such Commercial Contributor's * responsibility alone. Under this section, the Commercial * Contributor would have to defend claims against the other * Contributors related to those performance claims and * warranties, and if a court requires any other Contributor * to pay any damages as a result, the Commercial Contributor * must pay those damages. * * * 5. NO WARRANTY * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE * PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR * IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR * CONDITIONS OF TITLE, NO - INFRINGEMENT, MERCHANTABILITY OR * FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely * responsible for determining the appropriateness of using * and distributing the Program and assumes all risks * associated with its exercise of rights under this * Agreement, including but not limited to the risks and * costs of program errors, compliance with applicable laws, * damage to or loss of data, programs or equipment, and * unavailability or interruption of operations. * * 6. DISCLAIMER OF LIABILITY * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER * RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION * LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE * OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * 7. GENERAL * * If any provision of this Agreement is invalid or * unenforceable under applicable law, it shall not affect * the validity or enforceability of the remainder of the * terms of this Agreement, and without further action by the * parties hereto, such provision shall be reformed to the * minimum extent necessary to make such provision valid and * enforceable. * * * If Recipient institutes patent litigation against a * Contributor with respect to a patent applicable to * software (including a cros - claim or counterclaim in a * lawsuit), then any patent licenses granted by that * Contributor to such Recipient under this Agreement shall * terminate as of the date such litigation is filed. In * addition, If Recipient institutes patent litigation * against any entity (including a cros - claim or * counterclaim in a lawsuit) alleging that the Program * itself (excluding combinations of the Program with other * software or hardware) infringes such Recipient's * patent(s), then such Recipient's rights granted under * Section 2(b) shall terminate as of the date such * litigation is filed. * * All Recipient's rights under this Agreement shall * terminate if it fails to comply with any of the material * terms or conditions of this Agreement and does not cure * such failure in a reasonable period of time after becoming * aware of such noncompliance. If all Recipient's rights * under this Agreement terminate, Recipient agrees to cease * use and distribution of the Program as soon as reasonably * practicable. However, Recipient's obligations under this * Agreement and any licenses granted by Recipient relating * to the Program shall continue and survive. * * Everyone is permitted to copy and distribute copies of * this Agreement, but in order to avoid inconsistency the * Agreement is copyrighted and may only be modified in the * following manner. The Agreement Steward reserves the right * to publish new versions (including revisions) of this * Agreement from time to time. No one other than the * Agreement Steward has the right to modify this Agreement. * * IBM is the initial Agreement Steward. IBM may assign the * responsibility to serve as the Agreement Steward to a * suitable separate entity. Each new version of the * Agreement will be given a distinguishing version number. * The Program (including Contributions) may always be * distributed subject to the version of the Agreement under * which it was received. In addition, after a new version of * the Agreement is published, Contributor may elect to * distribute the Program (including its Contributions) under * the new version. Except as expressly stated in Sections * 2(a) and 2(b) above, Recipient receives no rights or * licenses to the intellectual property of any Contributor * under this Agreement, whether expressly, by implication, * estoppel or otherwise. All rights in the Program not * expressly granted under this Agreement are reserved. * * * This Agreement is governed by the laws of the State of New * York and the intellectual property laws of the United * States of America. No party to this Agreement will bring a * legal action under this Agreement more than one year after * the cause of action arose. Each party waives its rights to * a jury trial in any resulting litigation. * * * * (C) COPYRIGHT International Business Machines Corp. 2001, 2002 */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include "tpmtok_int.h" CK_RV data_object_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode) { return (template_check_required_base_attributes(tmpl, mode)); } /* * data_object_set_default_attributes() * * Set the default attributes for data objects: * * CKA_APPLICATION : empty string * CKA_VALUE : empty byte array */ CK_RV data_object_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode) { CK_ATTRIBUTE *class_attr = NULL; CK_ATTRIBUTE *app_attr = NULL; CK_ATTRIBUTE *value_attr = NULL; if (mode) app_attr = NULL; class_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + sizeof (CK_OBJECT_CLASS)); app_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE)); value_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE)); if (! class_attr || ! app_attr || ! value_attr) { if (class_attr) free(class_attr); if (app_attr) free(app_attr); if (value_attr) free(value_attr); return (CKR_HOST_MEMORY); } app_attr->type = CKA_APPLICATION; app_attr->ulValueLen = 0; // empty string app_attr->pValue = NULL; value_attr->type = CKA_VALUE; value_attr->ulValueLen = 0; // empty byte array value_attr->pValue = NULL; class_attr->type = CKA_CLASS; class_attr->ulValueLen = sizeof (CK_OBJECT_CLASS); class_attr->pValue = (CK_BYTE *)class_attr + sizeof (CK_ATTRIBUTE); *(CK_OBJECT_CLASS *)class_attr->pValue = CKO_DATA; (void) template_update_attribute(tmpl, class_attr); (void) template_update_attribute(tmpl, app_attr); (void) template_update_attribute(tmpl, value_attr); return (CKR_OK); } CK_RV data_object_validate_attribute(TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode) { if (! attr) { return (CKR_FUNCTION_FAILED); } switch (attr->type) { case CKA_APPLICATION: case CKA_VALUE: return (CKR_OK); default: return (template_validate_base_attribute(tmpl, attr, mode)); } } /* * The Initial Developer of the Original Code is International * Business Machines Corporation. Portions created by IBM * Corporation are Copyright (C) 2005 International Business * Machines Corporation. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the Common Public License as published by * IBM Corporation; either version 1 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * Common Public License for more details. * * You should have received a copy of the Common Public License * along with this program; if not, a copy can be viewed at * http://www.opensource.org/licenses/cpl1.0.php. */ /* (C) COPYRIGHT International Business Machines Corp. 2001, 2002, 2005 */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include "tpmtok_int.h" CK_RV decr_mgr_init( SESSION *sess, ENCR_DECR_CONTEXT *ctx, CK_ULONG operation, CK_MECHANISM *mech, CK_OBJECT_HANDLE key_handle) { OBJECT * key_obj = NULL; CK_ATTRIBUTE * attr = NULL; CK_BYTE *ptr = NULL; CK_KEY_TYPE keytype; CK_BBOOL flag; CK_RV rc; if (! sess) { return (CKR_FUNCTION_FAILED); } if (ctx->active != FALSE) { return (CKR_OPERATION_ACTIVE); } if (operation == OP_DECRYPT_INIT) { rc = object_mgr_find_in_map1(sess->hContext, key_handle, &key_obj); if (rc != CKR_OK) { return (CKR_KEY_HANDLE_INVALID); } rc = template_attribute_find(key_obj->template, CKA_DECRYPT, &attr); if (rc == FALSE) { return (CKR_KEY_FUNCTION_NOT_PERMITTED); } else { flag = *(CK_BBOOL *)attr->pValue; if (flag != TRUE) { return (CKR_KEY_FUNCTION_NOT_PERMITTED); } } } else if (operation == OP_UNWRAP) { rc = object_mgr_find_in_map1(sess->hContext, key_handle, &key_obj); if (rc != CKR_OK) { return (CKR_WRAPPING_KEY_HANDLE_INVALID); } rc = template_attribute_find(key_obj->template, CKA_UNWRAP, &attr); if (rc == FALSE) { return (CKR_FUNCTION_FAILED); } else { flag = *(CK_BBOOL *)(attr->pValue); if (flag == FALSE) { return (CKR_FUNCTION_FAILED); } } } else { return (CKR_FUNCTION_FAILED); } switch (mech->mechanism) { case CKM_RSA_PKCS: { if (mech->ulParameterLen != 0) return (CKR_MECHANISM_PARAM_INVALID); rc = template_attribute_find(key_obj->template, CKA_KEY_TYPE, &attr); if (rc == FALSE) { return (CKR_KEY_TYPE_INCONSISTENT); } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_RSA) { return (CKR_KEY_TYPE_INCONSISTENT); } } ctx->context_len = 0; ctx->context = NULL; } break; default: return (CKR_MECHANISM_INVALID); } if (mech->ulParameterLen > 0) { ptr = (CK_BYTE *)malloc(mech->ulParameterLen); if (! ptr) { return (CKR_HOST_MEMORY); } (void) memcpy(ptr, mech->pParameter, mech->ulParameterLen); } ctx->key = key_handle; ctx->mech.ulParameterLen = mech->ulParameterLen; ctx->mech.mechanism = mech->mechanism; ctx->mech.pParameter = ptr; ctx->multi = FALSE; ctx->active = TRUE; return (CKR_OK); } CK_RV decr_mgr_cleanup(ENCR_DECR_CONTEXT *ctx) { if (! ctx) { return (CKR_FUNCTION_FAILED); } ctx->key = 0; ctx->mech.ulParameterLen = 0; ctx->mech.mechanism = 0; ctx->multi = FALSE; ctx->active = FALSE; ctx->context_len = 0; if (ctx->mech.pParameter) { free(ctx->mech.pParameter); ctx->mech.pParameter = NULL; } if (ctx->context) { free(ctx->context); ctx->context = NULL; } return (CKR_OK); } CK_RV decr_mgr_decrypt(SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { if (! sess || ! ctx) { return (CKR_FUNCTION_FAILED); } if (ctx->active == FALSE) { return (CKR_OPERATION_NOT_INITIALIZED); } if ((length_only == FALSE) && (! in_data || ! out_data)) { return (CKR_FUNCTION_FAILED); } if (ctx->multi == TRUE) { return (CKR_OPERATION_ACTIVE); } switch (ctx->mech.mechanism) { case CKM_RSA_PKCS: return (rsa_pkcs_decrypt(sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len)); default: return (CKR_MECHANISM_INVALID); } } /* * Common Public License Version 0.5 * * THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF * THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, * REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES * RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. * * 1. DEFINITIONS * * "Contribution" means: * a) in the case of the initial Contributor, the * initial code and documentation distributed under * this Agreement, and * * b) in the case of each subsequent Contributor: * i) changes to the Program, and * ii) additions to the Program; * * where such changes and/or additions to the Program * originate from and are distributed by that * particular Contributor. A Contribution 'originates' * from a Contributor if it was added to the Program * by such Contributor itself or anyone acting on such * Contributor's behalf. Contributions do not include * additions to the Program which: (i) are separate * modules of software distributed in conjunction with * the Program under their own license agreement, and * (ii) are not derivative works of the Program. * * * "Contributor" means any person or entity that distributes * the Program. * * "Licensed Patents " mean patent claims licensable by a * Contributor which are necessarily infringed by the use or * sale of its Contribution alone or when combined with the * Program. * * "Program" means the Contributions distributed in * accordance with this Agreement. * * "Recipient" means anyone who receives the Program under * this Agreement, including all Contributors. * * 2. GRANT OF RIGHTS * * a) Subject to the terms of this Agreement, each * Contributor hereby grants Recipient a * no - exclusive, worldwide, royalt - free copyright * license to reproduce, prepare derivative works of, * publicly display, publicly perform, distribute and * sublicense the Contribution of such Contributor, if * any, and such derivative works, in source code and * object code form. * * b) Subject to the terms of this Agreement, each * Contributor hereby grants Recipient a * no - exclusive, worldwide, royalt - free patent * license under Licensed Patents to make, use, sell, * offer to sell, import and otherwise transfer the * Contribution of such Contributor, if any, in source * code and object code form. This patent license * shall apply to the combination of the Contribution * and the Program if, at the time the Contribution is * added by the Contributor, such addition of the * Contribution causes such combination to be covered * by the Licensed Patents. The patent license shall * not apply to any other combinations which include * the Contribution. No hardware per se is licensed * hereunder. * * c) Recipient understands that although each * Contributor grants the licenses to its * Contributions set forth herein, no assurances are * provided by any Contributor that the Program does * not infringe the patent or other intellectual * property rights of any other entity. Each * Contributor disclaims any liability to Recipient * for claims brought by any other entity based on * infringement of intellectual property rights or * otherwise. As a condition to exercising the rights * and licenses granted hereunder, each Recipient * hereby assumes sole responsibility to secure any * other intellectual property rights needed, if any. * * For example, if a third party patent license is * required to allow Recipient to distribute the * Program, it is Recipient's responsibility to * acquire that license before distributing the * Program. * * d) Each Contributor represents that to its * knowledge it has sufficient copyright rights in its * Contribution, if any, to grant the copyright * license set forth in this Agreement. * * 3. REQUIREMENTS * * A Contributor may choose to distribute the Program in * object code form under its own license agreement, provided * that: * a) it complies with the terms and conditions of * this Agreement; and * * b) its license agreement: * i) effectively disclaims on behalf of all * Contributors all warranties and conditions, express * and implied, including warranties or conditions of * title and no - infringement, and implied warranties * or conditions of merchantability and fitness for a * particular purpose; * * ii) effectively excludes on behalf of all * Contributors all liability for damages, including * direct, indirect, special, incidental and * consequential damages, such as lost profits; * * iii) states that any provisions which differ from * this Agreement are offered by that Contributor * alone and not by any other party; and * * iv) states that source code for the Program is * available from such Contributor, and informs * licensees how to obtain it in a reasonable manner * on or through a medium customarily used for * software exchange. * * When the Program is made available in source code form: * a) it must be made available under this Agreement; * and * b) a copy of this Agreement must be included with * each copy of the Program. * * Contributors may not remove or alter any copyright notices * contained within the Program. * * Each Contributor must identify itself as the originator of * its Contribution, if any, in a manner that reasonably * allows subsequent Recipients to identify the originator of * the Contribution. * * * 4. COMMERCIAL DISTRIBUTION * * Commercial distributors of software may accept certain * responsibilities with respect to end users, business * partners and the like. While this license is intended to * facilitate the commercial use of the Program, the * Contributor who includes the Program in a commercial * product offering should do so in a manner which does not * create potential liability for other Contributors. * Therefore, if a Contributor includes the Program in a * commercial product offering, such Contributor ("Commercial * Contributor") hereby agrees to defend and indemnify every * other Contributor ("Indemnified Contributor") against any * losses, damages and costs (collectively "Losses") arising * from claims, lawsuits and other legal actions brought by a * third party against the Indemnified Contributor to the * extent caused by the acts or omissions of such Commercial * Contributor in connection with its distribution of the * Program in a commercial product offering. The obligations * in this section do not apply to any claims or Losses * relating to any actual or alleged intellectual property * infringement. In order to qualify, an Indemnified * Contributor must: a) promptly notify the Commercial * Contributor in writing of such claim, and b) allow the * Commercial Contributor to control, and cooperate with the * Commercial Contributor in, the defense and any related * settlement negotiations. The Indemnified Contributor may * participate in any such claim at its own expense. * * * For example, a Contributor might include the Program in a * commercial product offering, Product X. That Contributor * is then a Commercial Contributor. If that Commercial * Contributor then makes performance claims, or offers * warranties related to Product X, those performance claims * and warranties are such Commercial Contributor's * responsibility alone. Under this section, the Commercial * Contributor would have to defend claims against the other * Contributors related to those performance claims and * warranties, and if a court requires any other Contributor * to pay any damages as a result, the Commercial Contributor * must pay those damages. * * * 5. NO WARRANTY * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE * PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR * IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR * CONDITIONS OF TITLE, NO - INFRINGEMENT, MERCHANTABILITY OR * FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely * responsible for determining the appropriateness of using * and distributing the Program and assumes all risks * associated with its exercise of rights under this * Agreement, including but not limited to the risks and * costs of program errors, compliance with applicable laws, * damage to or loss of data, programs or equipment, and * unavailability or interruption of operations. * * 6. DISCLAIMER OF LIABILITY * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER * RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION * LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE * OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * 7. GENERAL * * If any provision of this Agreement is invalid or * unenforceable under applicable law, it shall not affect * the validity or enforceability of the remainder of the * terms of this Agreement, and without further action by the * parties hereto, such provision shall be reformed to the * minimum extent necessary to make such provision valid and * enforceable. * * * If Recipient institutes patent litigation against a * Contributor with respect to a patent applicable to * software (including a cros - claim or counterclaim in a * lawsuit), then any patent licenses granted by that * Contributor to such Recipient under this Agreement shall * terminate as of the date such litigation is filed. In * addition, If Recipient institutes patent litigation * against any entity (including a cros - claim or * counterclaim in a lawsuit) alleging that the Program * itself (excluding combinations of the Program with other * software or hardware) infringes such Recipient's * patent(s), then such Recipient's rights granted under * Section 2(b) shall terminate as of the date such * litigation is filed. * * All Recipient's rights under this Agreement shall * terminate if it fails to comply with any of the material * terms or conditions of this Agreement and does not cure * such failure in a reasonable period of time after becoming * aware of such noncompliance. If all Recipient's rights * under this Agreement terminate, Recipient agrees to cease * use and distribution of the Program as soon as reasonably * practicable. However, Recipient's obligations under this * Agreement and any licenses granted by Recipient relating * to the Program shall continue and survive. * * Everyone is permitted to copy and distribute copies of * this Agreement, but in order to avoid inconsistency the * Agreement is copyrighted and may only be modified in the * following manner. The Agreement Steward reserves the right * to publish new versions (including revisions) of this * Agreement from time to time. No one other than the * Agreement Steward has the right to modify this Agreement. * * IBM is the initial Agreement Steward. IBM may assign the * responsibility to serve as the Agreement Steward to a * suitable separate entity. Each new version of the * Agreement will be given a distinguishing version number. * The Program (including Contributions) may always be * distributed subject to the version of the Agreement under * which it was received. In addition, after a new version of * the Agreement is published, Contributor may elect to * distribute the Program (including its Contributions) under * the new version. Except as expressly stated in Sections * 2(a) and 2(b) above, Recipient receives no rights or * licenses to the intellectual property of any Contributor * under this Agreement, whether expressly, by implication, * estoppel or otherwise. All rights in the Program not * expressly granted under this Agreement are reserved. * * * This Agreement is governed by the laws of the State of New * York and the intellectual property laws of the United * States of America. No party to this Agreement will bring a * legal action under this Agreement more than one year after * the cause of action arose. Each party waives its rights to * a jury trial in any resulting litigation. * * * * (C) COPYRIGHT International Business Machines Corp. 2001, 2002 */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Digest manager routines */ #include "tpmtok_int.h" CK_RV digest_mgr_init(SESSION *sess, DIGEST_CONTEXT *ctx, CK_MECHANISM *mech) { if (! sess || ! ctx) { return (CKR_FUNCTION_FAILED); } if (ctx->active != FALSE) { return (CKR_OPERATION_ACTIVE); } switch (mech->mechanism) { case CKM_SHA_1: { ctx->context_len = sizeof (SHA1_CTX); ctx->context.sha1ctx = (SHA1_CTX *) malloc(ctx->context_len); if (!ctx->context.sha1ctx) return (CKR_HOST_MEMORY); SHA1Init(ctx->context.sha1ctx); } break; case CKM_MD5: { ctx->context_len = sizeof (MD5_CTX); ctx->context.md5ctx = (MD5_CTX *) malloc(ctx->context_len); if (! ctx->context.md5ctx) { return (CKR_HOST_MEMORY); } MD5Init(ctx->context.md5ctx); } break; default: return (CKR_MECHANISM_INVALID); } ctx->mech.ulParameterLen = mech->ulParameterLen; ctx->mech.mechanism = mech->mechanism; ctx->mech.pParameter = mech->pParameter; ctx->multi = FALSE; ctx->active = TRUE; return (CKR_OK); } CK_RV digest_mgr_cleanup(DIGEST_CONTEXT *ctx) { if (!ctx) { return (CKR_FUNCTION_FAILED); } if (ctx->mech.mechanism == CKM_MD5) { free(ctx->context.md5ctx); ctx->context.md5ctx = NULL; } else if (ctx->mech.mechanism == CKM_SHA_1) { free(ctx->context.sha1ctx); ctx->context.sha1ctx = NULL; } ctx->mech.ulParameterLen = 0; ctx->mech.pParameter = NULL; ctx->mech.mechanism = 0; ctx->multi = FALSE; ctx->active = FALSE; ctx->context_len = 0; return (CKR_OK); } CK_RV digest_mgr_digest(SESSION *sess, CK_BBOOL length_only, DIGEST_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { if (! sess || ! ctx) { return (CKR_FUNCTION_FAILED); } if (ctx->active == FALSE) { return (CKR_OPERATION_NOT_INITIALIZED); } if ((length_only == FALSE) && (! in_data || ! out_data)) { return (CKR_FUNCTION_FAILED); } if (ctx->multi == TRUE) { return (CKR_OPERATION_ACTIVE); } switch (ctx->mech.mechanism) { case CKM_SHA_1: if (!length_only && *out_data_len < SHA1_DIGEST_LENGTH) return (CKR_BUFFER_TOO_SMALL); return (sha1_hash(sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len)); case CKM_MD5: if (!length_only && *out_data_len < MD5_DIGEST_LENGTH) return (CKR_BUFFER_TOO_SMALL); return (md5_hash(sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len)); default: return (CKR_FUNCTION_FAILED); } } CK_RV digest_mgr_digest_update(SESSION *sess, DIGEST_CONTEXT *ctx, CK_BYTE *data, CK_ULONG data_len) { if (! sess || ! ctx) { return (CKR_FUNCTION_FAILED); } if (ctx->active == FALSE) { return (CKR_OPERATION_NOT_INITIALIZED); } ctx->multi = TRUE; switch (ctx->mech.mechanism) { case CKM_SHA_1: SHA1Update(ctx->context.sha1ctx, data, data_len); return (CKR_OK); case CKM_MD5: MD5Update(ctx->context.md5ctx, data, data_len); return (CKR_OK); default: return (CKR_MECHANISM_INVALID); } } CK_RV digest_mgr_digest_key(SESSION * sess, DIGEST_CONTEXT *ctx, CK_OBJECT_HANDLE key_handle) { CK_ATTRIBUTE *attr = NULL; OBJECT * key_obj = NULL; CK_OBJECT_CLASS class; CK_RV rc; if (!sess || !ctx) { return (CKR_FUNCTION_FAILED); } rc = object_mgr_find_in_map1(sess->hContext, key_handle, &key_obj); if (rc != CKR_OK) { return (CKR_KEY_HANDLE_INVALID); } rc = template_attribute_find(key_obj->template, CKA_CLASS, &attr); if (rc == FALSE) return (CKR_KEY_INDIGESTIBLE); else class = *(CK_OBJECT_CLASS *)attr->pValue; if (class != CKO_SECRET_KEY) return (CKR_KEY_INDIGESTIBLE); rc = template_attribute_find(key_obj->template, CKA_VALUE, &attr); if (! rc) return (CKR_KEY_INDIGESTIBLE); rc = digest_mgr_digest_update(sess, ctx, attr->pValue, attr->ulValueLen); return (rc); } CK_RV digest_mgr_digest_final(SESSION *sess, DIGEST_CONTEXT *ctx, CK_BYTE *hash, CK_ULONG *hash_len) { if (! sess || ! ctx) { return (CKR_FUNCTION_FAILED); } if (ctx->active == FALSE) { return (CKR_OPERATION_NOT_INITIALIZED); } ctx->multi = FALSE; if (hash == NULL && hash_len == NULL) return (CKR_ARGUMENTS_BAD); switch (ctx->mech.mechanism) { case CKM_SHA_1: if (hash == NULL) { *hash_len = SHA1_DIGEST_LENGTH; return (CKR_OK); } if (*hash_len < SHA1_DIGEST_LENGTH) return (CKR_BUFFER_TOO_SMALL); SHA1Final(hash, ctx->context.sha1ctx); if (hash_len) *hash_len = SHA1_DIGEST_LENGTH; return (CKR_OK); case CKM_MD5: if (hash == NULL) { *hash_len = MD5_DIGEST_LENGTH; return (CKR_OK); } if (*hash_len < MD5_DIGEST_LENGTH) return (CKR_BUFFER_TOO_SMALL); MD5Final(hash, ctx->context.md5ctx); if (hash_len) *hash_len = MD5_DIGEST_LENGTH; return (CKR_OK); default: return (CKR_MECHANISM_INVALID); } } /* * The Initial Developer of the Original Code is International * Business Machines Corporation. Portions created by IBM * Corporation are Copyright (C) 2005 International Business * Machines Corporation. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the Common Public License as published by * IBM Corporation; either version 1 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * Common Public License for more details. * * You should have received a copy of the Common Public License * along with this program; if not, a copy can be viewed at * http://www.opensource.org/licenses/cpl1.0.php. */ /* (C) COPYRIGHT International Business Machines Corp. 2001, 2002, 2005 */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include "tpmtok_int.h" CK_RV encr_mgr_init(SESSION * sess, ENCR_DECR_CONTEXT * ctx, CK_ULONG operation, CK_MECHANISM * mech, CK_OBJECT_HANDLE key_handle) { OBJECT * key_obj = NULL; CK_ATTRIBUTE * attr = NULL; CK_BYTE * ptr = NULL; CK_KEY_TYPE keytype; CK_BBOOL flag; CK_RV rc; if (! sess || ! ctx || ! mech) { return (CKR_FUNCTION_FAILED); } if (ctx->active != FALSE) { return (CKR_OPERATION_ACTIVE); } if (operation == OP_ENCRYPT_INIT) { rc = object_mgr_find_in_map1(sess->hContext, key_handle, &key_obj); if (rc != CKR_OK) { return (CKR_KEY_HANDLE_INVALID); } rc = template_attribute_find(key_obj->template, CKA_ENCRYPT, &attr); if (rc == FALSE) { return (CKR_KEY_FUNCTION_NOT_PERMITTED); } else { flag = *(CK_BBOOL *)attr->pValue; if (flag != TRUE) { return (CKR_KEY_FUNCTION_NOT_PERMITTED); } } } else if (operation == OP_WRAP) { rc = object_mgr_find_in_map1(sess->hContext, key_handle, &key_obj); if (rc != CKR_OK) { return (CKR_WRAPPING_KEY_HANDLE_INVALID); } rc = template_attribute_find(key_obj->template, CKA_WRAP, &attr); if (rc == FALSE) { return (CKR_KEY_NOT_WRAPPABLE); } else { flag = *(CK_BBOOL *)attr->pValue; if (flag == FALSE) { return (CKR_KEY_NOT_WRAPPABLE); } } } else { return (CKR_FUNCTION_FAILED); } switch (mech->mechanism) { case CKM_RSA_PKCS: { if (mech->ulParameterLen != 0) { return (CKR_MECHANISM_PARAM_INVALID); } rc = template_attribute_find(key_obj->template, CKA_KEY_TYPE, &attr); if (rc == FALSE) { return (CKR_KEY_TYPE_INCONSISTENT); } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_RSA) { return (CKR_KEY_TYPE_INCONSISTENT); } } ctx->context_len = 0; ctx->context = NULL; } break; default: return (CKR_MECHANISM_INVALID); } if (mech->ulParameterLen > 0) { ptr = (CK_BYTE *)malloc(mech->ulParameterLen); if (! ptr) { return (CKR_HOST_MEMORY); } (void) memcpy(ptr, mech->pParameter, mech->ulParameterLen); } ctx->key = key_handle; ctx->mech.ulParameterLen = mech->ulParameterLen; ctx->mech.mechanism = mech->mechanism; ctx->mech.pParameter = ptr; ctx->multi = FALSE; ctx->active = TRUE; return (CKR_OK); } CK_RV encr_mgr_cleanup(ENCR_DECR_CONTEXT *ctx) { if (! ctx) { return (CKR_FUNCTION_FAILED); } ctx->key = 0; ctx->mech.ulParameterLen = 0; ctx->mech.mechanism = 0; ctx->multi = FALSE; ctx->active = FALSE; ctx->context_len = 0; if (ctx->mech.pParameter) { free(ctx->mech.pParameter); ctx->mech.pParameter = NULL; } if (ctx->context) { free(ctx->context); ctx->context = NULL; } return (CKR_OK); } CK_RV encr_mgr_encrypt(SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { if (! sess || ! ctx) { return (CKR_FUNCTION_FAILED); } if (ctx->active == FALSE) { return (CKR_OPERATION_NOT_INITIALIZED); } if ((length_only == FALSE) && (! in_data || ! out_data)) { return (CKR_FUNCTION_FAILED); } if (ctx->multi == TRUE) { return (CKR_OPERATION_ACTIVE); } switch (ctx->mech.mechanism) { case CKM_RSA_PKCS: return (rsa_pkcs_encrypt(sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len)); default: return (CKR_MECHANISM_INVALID); } } /* (C) COPYRIGHT International Business Machines Corp. 2001, 2002, 2005 */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include "tpmtok_int.h" CK_BBOOL initialized = FALSE; pthread_mutex_t native_mutex; pthread_mutex_t pkcs_mutex, obj_list_mutex, sess_list_mutex, login_mutex; void *xproclock; DL_NODE *sess_list = NULL; DL_NODE *sess_obj_list = NULL; DL_NODE *publ_token_obj_list = NULL; DL_NODE *priv_token_obj_list = NULL; DL_NODE *object_map = NULL; CK_STATE global_login_state = 0; LW_SHM_TYPE *global_shm; CK_ULONG next_session_handle = 1; CK_ULONG next_object_handle = 1; TOKEN_DATA *nv_token_data = NULL; extern CK_RV LW_Initialize(); extern CK_RV SC_GetFunctionList(); extern CK_RV SC_GetTokenInfo(); extern CK_RV SC_GetMechanismList(); extern CK_RV SC_GetMechanismInfo(); extern CK_RV SC_InitToken(); extern CK_RV SC_InitPIN(); extern CK_RV SC_SetPIN(); extern CK_RV SC_OpenSession(); extern CK_RV SC_CloseSession(); extern CK_RV SC_CloseAllSessions(); extern CK_RV SC_GetSessionInfo(); extern CK_RV SC_GetOperationState(); extern CK_RV SC_SetOperationState(); extern CK_RV SC_Login(); extern CK_RV SC_Logout(); extern CK_RV SC_CreateObject(); extern CK_RV SC_CopyObject(); extern CK_RV SC_DestroyObject(); extern CK_RV SC_GetObjectSize(); extern CK_RV SC_GetAttributeValue(); extern CK_RV SC_SetAttributeValue(); extern CK_RV SC_FindObjectsInit(); extern CK_RV SC_FindObjects(); extern CK_RV SC_FindObjectsFinal(); extern CK_RV SC_EncryptInit(); extern CK_RV SC_Encrypt(); extern CK_RV SC_EncryptUpdate(); extern CK_RV SC_EncryptFinal(); extern CK_RV SC_DecryptInit(); extern CK_RV SC_Decrypt(); extern CK_RV SC_DecryptUpdate(); extern CK_RV SC_DecryptFinal(); extern CK_RV SC_DigestInit(); extern CK_RV SC_Digest(); extern CK_RV SC_DigestUpdate(); extern CK_RV SC_DigestKey(); extern CK_RV SC_DigestFinal(); extern CK_RV SC_SignInit(); extern CK_RV SC_Sign(); extern CK_RV SC_SignUpdate(); extern CK_RV SC_SignFinal(); extern CK_RV SC_SignRecoverInit(); extern CK_RV SC_SignRecover(); extern CK_RV SC_VerifyInit(); extern CK_RV SC_Verify(); extern CK_RV SC_VerifyUpdate(); extern CK_RV SC_VerifyFinal(); extern CK_RV SC_VerifyRecoverInit(); extern CK_RV SC_VerifyRecover(); extern CK_RV SC_DigestEncryptUpdate(); extern CK_RV SC_DecryptDigestUpdate(); extern CK_RV SC_SignEncryptUpdate(); extern CK_RV SC_DecryptVerifyUpdate(); extern CK_RV SC_GenerateKey(); extern CK_RV SC_GenerateKeyPair(); extern CK_RV SC_WrapKey(); extern CK_RV SC_UnwrapKey(); extern CK_RV SC_DeriveKey(); extern CK_RV SC_SeedRandom(); extern CK_RV SC_GenerateRandom(); extern CK_RV SC_GetFunctionStatus(); extern CK_RV SC_CancelFunction(); extern CK_RV SC_WaitForSlotEvent(); CK_BYTE ber_rsaEncryption[] = { 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 }; CK_BYTE ber_md5WithRSAEncryption[] = { 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x04 }; CK_BYTE ber_sha1WithRSAEncryption[] = { 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05 }; CK_BYTE ber_AlgMd5[] = { 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00 }; CK_BYTE ber_AlgSha1[] = { 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00 }; CK_BYTE ber_AlgIdRSAEncryption[] = { 0x30, 0x0D, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00 }; CK_ULONG ber_rsaEncryptionLen = sizeof (ber_rsaEncryption); CK_ULONG ber_md5WithRSAEncryptionLen = sizeof (ber_md5WithRSAEncryption); CK_ULONG ber_sha1WithRSAEncryptionLen = sizeof (ber_sha1WithRSAEncryption); CK_ULONG ber_AlgMd5Len = sizeof (ber_AlgMd5); CK_ULONG ber_AlgSha1Len = sizeof (ber_AlgSha1); CK_ULONG ber_AlgIdRSAEncryptionLen = sizeof (ber_AlgIdRSAEncryption); MECH_LIST_ELEMENT mech_list[] = { { CKM_RSA_PKCS_KEY_PAIR_GEN, {512, 2048, CKF_HW | CKF_GENERATE_KEY_PAIR } }, { CKM_RSA_PKCS, {512, 2048, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP | CKF_SIGN | CKF_VERIFY | CKF_SIGN_RECOVER | CKF_VERIFY_RECOVER } }, { CKM_RSA_PKCS_OAEP, {512, 2048, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP | CKF_SIGN | CKF_VERIFY | CKF_SIGN_RECOVER | CKF_VERIFY_RECOVER }}, #if 0 /* No RSA_X_509 support for now... */ { CKM_RSA_X_509, {512, 2048, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP | CKF_SIGN | CKF_VERIFY | CKF_SIGN_RECOVER | CKF_VERIFY_RECOVER } }, #endif {CKM_MD5_RSA_PKCS, {512, 2048, CKF_HW | CKF_SIGN | CKF_VERIFY } }, { CKM_SHA1_RSA_PKCS, {512, 2048, CKF_HW | CKF_SIGN | CKF_VERIFY } }, {CKM_SHA_1, {0, 0, CKF_DIGEST } }, {CKM_SHA_1_HMAC, {0, 0, CKF_SIGN | CKF_VERIFY } }, {CKM_SHA_1_HMAC_GENERAL, {0, 0, CKF_SIGN | CKF_VERIFY } }, {CKM_MD5, {0, 0, CKF_DIGEST } }, {CKM_MD5_HMAC, {0, 0, CKF_SIGN | CKF_VERIFY } }, {CKM_MD5_HMAC_GENERAL, {0, 0, CKF_SIGN | CKF_VERIFY } }, }; CK_ULONG mech_list_len = (sizeof (mech_list) / sizeof (MECH_LIST_ELEMENT)); /* * default SO pin hash values * * default SO pin = "87654321" */ CK_BYTE default_so_pin_md5[MD5_DIGEST_LENGTH] = { 0x5E, 0x86, 0x67, 0xA4, 0x39, 0xC6, 0x8F, 0x51, 0x45, 0xDD, 0x2F, 0xCB, 0xEC, 0xF0, 0x22, 0x09 }; CK_BYTE default_so_pin_sha[SHA1_DIGEST_LENGTH] = { 0xA7, 0xD5, 0x79, 0xBA, 0x76, 0x39, 0x80, 0x70, 0xEA, 0xE6, 0x54, 0xC3, 0x0F, 0xF1, 0x53, 0xA4, 0xC2, 0x73, 0x27, 0x2A }; /* SH - 1 of "12345678" */ CK_BYTE default_user_pin_sha[SHA1_DIGEST_LENGTH] = { 0x7c, 0x22, 0x2f, 0xb2, 0x92, 0x7d, 0x82, 0x8a, 0xf2, 0x2f, 0x59, 0x21, 0x34, 0xe8, 0x93, 0x24, 0x80, 0x63, 0x7c, 0x0d }; CK_BYTE user_pin_md5[MD5_DIGEST_LENGTH]; CK_BYTE so_pin_md5[MD5_DIGEST_LENGTH]; /* * Common Public License Version 0.5 * * THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF * THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, * REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES * RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. * * 1. DEFINITIONS * * "Contribution" means: * a) in the case of the initial Contributor, the * initial code and documentation distributed under * this Agreement, and * * b) in the case of each subsequent Contributor: * i) changes to the Program, and * ii) additions to the Program; * * where such changes and/or additions to the Program * originate from and are distributed by that * particular Contributor. A Contribution 'originates' * from a Contributor if it was added to the Program * by such Contributor itself or anyone acting on such * Contributor's behalf. Contributions do not include * additions to the Program which: (i) are separate * modules of software distributed in conjunction with * the Program under their own license agreement, and * (ii) are not derivative works of the Program. * * * "Contributor" means any person or entity that distributes * the Program. * * "Licensed Patents " mean patent claims licensable by a * Contributor which are necessarily infringed by the use or * sale of its Contribution alone or when combined with the * Program. * * "Program" means the Contributions distributed in * accordance with this Agreement. * * "Recipient" means anyone who receives the Program under * this Agreement, including all Contributors. * * 2. GRANT OF RIGHTS * * a) Subject to the terms of this Agreement, each * Contributor hereby grants Recipient a * no - exclusive, worldwide, royalt - free copyright * license to reproduce, prepare derivative works of, * publicly display, publicly perform, distribute and * sublicense the Contribution of such Contributor, if * any, and such derivative works, in source code and * object code form. * * b) Subject to the terms of this Agreement, each * Contributor hereby grants Recipient a * no - exclusive, worldwide, royalt - free patent * license under Licensed Patents to make, use, sell, * offer to sell, import and otherwise transfer the * Contribution of such Contributor, if any, in source * code and object code form. This patent license * shall apply to the combination of the Contribution * and the Program if, at the time the Contribution is * added by the Contributor, such addition of the * Contribution causes such combination to be covered * by the Licensed Patents. The patent license shall * not apply to any other combinations which include * the Contribution. No hardware per se is licensed * hereunder. * * c) Recipient understands that although each * Contributor grants the licenses to its * Contributions set forth herein, no assurances are * provided by any Contributor that the Program does * not infringe the patent or other intellectual * property rights of any other entity. Each * Contributor disclaims any liability to Recipient * for claims brought by any other entity based on * infringement of intellectual property rights or * otherwise. As a condition to exercising the rights * and licenses granted hereunder, each Recipient * hereby assumes sole responsibility to secure any * other intellectual property rights needed, if any. * * For example, if a third party patent license is * required to allow Recipient to distribute the * Program, it is Recipient's responsibility to * acquire that license before distributing the * Program. * * d) Each Contributor represents that to its * knowledge it has sufficient copyright rights in its * Contribution, if any, to grant the copyright * license set forth in this Agreement. * * 3. REQUIREMENTS * * A Contributor may choose to distribute the Program in * object code form under its own license agreement, provided * that: * a) it complies with the terms and conditions of * this Agreement; and * * b) its license agreement: * i) effectively disclaims on behalf of all * Contributors all warranties and conditions, express * and implied, including warranties or conditions of * title and no - infringement, and implied warranties * or conditions of merchantability and fitness for a * particular purpose; * * ii) effectively excludes on behalf of all * Contributors all liability for damages, including * direct, indirect, special, incidental and * consequential damages, such as lost profits; * * iii) states that any provisions which differ from * this Agreement are offered by that Contributor * alone and not by any other party; and * * iv) states that source code for the Program is * available from such Contributor, and informs * licensees how to obtain it in a reasonable manner * on or through a medium customarily used for * software exchange. * * When the Program is made available in source code form: * a) it must be made available under this Agreement; * and * b) a copy of this Agreement must be included with * each copy of the Program. * * Contributors may not remove or alter any copyright notices * contained within the Program. * * Each Contributor must identify itself as the originator of * its Contribution, if any, in a manner that reasonably * allows subsequent Recipients to identify the originator of * the Contribution. * * * 4. COMMERCIAL DISTRIBUTION * * Commercial distributors of software may accept certain * responsibilities with respect to end users, business * partners and the like. While this license is intended to * facilitate the commercial use of the Program, the * Contributor who includes the Program in a commercial * product offering should do so in a manner which does not * create potential liability for other Contributors. * Therefore, if a Contributor includes the Program in a * commercial product offering, such Contributor ("Commercial * Contributor") hereby agrees to defend and indemnify every * other Contributor ("Indemnified Contributor") against any * losses, damages and costs (collectively "Losses") arising * from claims, lawsuits and other legal actions brought by a * third party against the Indemnified Contributor to the * extent caused by the acts or omissions of such Commercial * Contributor in connection with its distribution of the * Program in a commercial product offering. The obligations * in this section do not apply to any claims or Losses * relating to any actual or alleged intellectual property * infringement. In order to qualify, an Indemnified * Contributor must: a) promptly notify the Commercial * Contributor in writing of such claim, and b) allow the * Commercial Contributor to control, and cooperate with the * Commercial Contributor in, the defense and any related * settlement negotiations. The Indemnified Contributor may * participate in any such claim at its own expense. * * * For example, a Contributor might include the Program in a * commercial product offering, Product X. That Contributor * is then a Commercial Contributor. If that Commercial * Contributor then makes performance claims, or offers * warranties related to Product X, those performance claims * and warranties are such Commercial Contributor's * responsibility alone. Under this section, the Commercial * Contributor would have to defend claims against the other * Contributors related to those performance claims and * warranties, and if a court requires any other Contributor * to pay any damages as a result, the Commercial Contributor * must pay those damages. * * * 5. NO WARRANTY * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE * PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR * IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR * CONDITIONS OF TITLE, NO - INFRINGEMENT, MERCHANTABILITY OR * FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely * responsible for determining the appropriateness of using * and distributing the Program and assumes all risks * associated with its exercise of rights under this * Agreement, including but not limited to the risks and * costs of program errors, compliance with applicable laws, * damage to or loss of data, programs or equipment, and * unavailability or interruption of operations. * * 6. DISCLAIMER OF LIABILITY * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER * RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION * LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE * OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * 7. GENERAL * * If any provision of this Agreement is invalid or * unenforceable under applicable law, it shall not affect * the validity or enforceability of the remainder of the * terms of this Agreement, and without further action by the * parties hereto, such provision shall be reformed to the * minimum extent necessary to make such provision valid and * enforceable. * * * If Recipient institutes patent litigation against a * Contributor with respect to a patent applicable to * software (including a cros - claim or counterclaim in a * lawsuit), then any patent licenses granted by that * Contributor to such Recipient under this Agreement shall * terminate as of the date such litigation is filed. In * addition, If Recipient institutes patent litigation * against any entity (including a cros - claim or * counterclaim in a lawsuit) alleging that the Program * itself (excluding combinations of the Program with other * software or hardware) infringes such Recipient's * patent(s), then such Recipient's rights granted under * Section 2(b) shall terminate as of the date such * litigation is filed. * * All Recipient's rights under this Agreement shall * terminate if it fails to comply with any of the material * terms or conditions of this Agreement and does not cure * such failure in a reasonable period of time after becoming * aware of such noncompliance. If all Recipient's rights * under this Agreement terminate, Recipient agrees to cease * use and distribution of the Program as soon as reasonably * practicable. However, Recipient's obligations under this * Agreement and any licenses granted by Recipient relating * to the Program shall continue and survive. * * Everyone is permitted to copy and distribute copies of * this Agreement, but in order to avoid inconsistency the * Agreement is copyrighted and may only be modified in the * following manner. The Agreement Steward reserves the right * to publish new versions (including revisions) of this * Agreement from time to time. No one other than the * Agreement Steward has the right to modify this Agreement. * * IBM is the initial Agreement Steward. IBM may assign the * responsibility to serve as the Agreement Steward to a * suitable separate entity. Each new version of the * Agreement will be given a distinguishing version number. * The Program (including Contributions) may always be * distributed subject to the version of the Agreement under * which it was received. In addition, after a new version of * the Agreement is published, Contributor may elect to * distribute the Program (including its Contributions) under * the new version. Except as expressly stated in Sections * 2(a) and 2(b) above, Recipient receives no rights or * licenses to the intellectual property of any Contributor * under this Agreement, whether expressly, by implication, * estoppel or otherwise. All rights in the Program not * expressly granted under this Agreement are reserved. * * * This Agreement is governed by the laws of the State of New * York and the intellectual property laws of the United * States of America. No party to this Agreement will bring a * legal action under this Agreement more than one year after * the cause of action arose. Each party waives its rights to * a jury trial in any resulting litigation. * * * * (C) COPYRIGHT International Business Machines Corp. 2001, 2002 */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include "tpmtok_int.h" CK_RV hwf_object_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode) { CK_ATTRIBUTE * attr = NULL; CK_BBOOL found; found = template_attribute_find(tmpl, CKA_HW_FEATURE_TYPE, &attr); if (! found) { if (mode == MODE_CREATE) { return (CKR_TEMPLATE_INCOMPLETE); } } return (template_check_required_base_attributes(tmpl, mode)); } CK_RV clock_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL found; if (mode == MODE_CREATE) { found = template_attribute_find(tmpl, CKA_VALUE, &attr); if (! found) { return (CKR_TEMPLATE_INCOMPLETE); } } return (hwf_object_check_required_attributes(tmpl, mode)); } CK_RV counter_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL found; if (mode == MODE_CREATE) { found = template_attribute_find(tmpl, CKA_VALUE, &attr); if (! found) { return (CKR_TEMPLATE_INCOMPLETE); } found = template_attribute_find(tmpl, CKA_HAS_RESET, &attr); if (! found) { return (CKR_TEMPLATE_INCOMPLETE); } found = template_attribute_find(tmpl, CKA_RESET_ON_INIT, &attr); if (! found) { return (CKR_TEMPLATE_INCOMPLETE); } } return (hwf_object_check_required_attributes(tmpl, mode)); } // hwf_object_validate_attribute() // CK_RV hwf_validate_attribute(TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode) { switch (attr->type) { case CKA_HW_FEATURE_TYPE: if (mode == MODE_CREATE) return (CKR_OK); else return (CKR_ATTRIBUTE_READ_ONLY); default: return (template_validate_base_attribute(tmpl, attr, mode)); } } CK_RV clock_validate_attribute(TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode) { switch (attr->type) { case CKA_VALUE: return (CKR_OK); default: return (hwf_validate_attribute(tmpl, attr, mode)); } } CK_RV counter_validate_attribute(TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode) { switch (attr->type) { case CKA_VALUE: /* Fall Through */ case CKA_HAS_RESET: /* Fall Through */ case CKA_RESET_ON_INIT: return (CKR_ATTRIBUTE_READ_ONLY); default: return (hwf_validate_attribute(tmpl, attr, mode)); } } CK_RV clock_set_default_attributes(TEMPLATE *tmpl) { CK_ATTRIBUTE *value_attr; value_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE)); if (! value_attr) { return (CKR_HOST_MEMORY); } value_attr->type = CKA_VALUE; value_attr->ulValueLen = 0; value_attr->pValue = NULL; (void) template_update_attribute(tmpl, value_attr); return (CKR_OK); } CK_RV counter_set_default_attributes(TEMPLATE *tmpl) { CK_ATTRIBUTE *value_attr; CK_ATTRIBUTE *hasreset_attr; CK_ATTRIBUTE *resetoninit_attr; value_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE)); hasreset_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + sizeof (CK_BBOOL)); resetoninit_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + sizeof (CK_BBOOL)); if (! value_attr || ! hasreset_attr || ! resetoninit_attr) { if (value_attr) free(value_attr); if (hasreset_attr) free(hasreset_attr); if (resetoninit_attr) free(resetoninit_attr); return (CKR_HOST_MEMORY); } value_attr->type = CKA_VALUE; value_attr->ulValueLen = 0; value_attr->pValue = NULL; hasreset_attr->type = CKA_HAS_RESET; hasreset_attr->ulValueLen = sizeof (CK_BBOOL); hasreset_attr->pValue = (CK_BYTE *)hasreset_attr + sizeof (CK_ATTRIBUTE); *(CK_BBOOL *)hasreset_attr->pValue = FALSE; /* Hmm... Not sure if we should be setting this here. */ resetoninit_attr->type = CKA_RESET_ON_INIT; resetoninit_attr->ulValueLen = sizeof (CK_BBOOL); resetoninit_attr->pValue = (CK_BYTE *)resetoninit_attr + sizeof (CK_ATTRIBUTE); *(CK_BBOOL *)resetoninit_attr->pValue = FALSE; (void) template_update_attribute(tmpl, value_attr); (void) template_update_attribute(tmpl, hasreset_attr); (void) template_update_attribute(tmpl, resetoninit_attr); return (CKR_OK); } /* * Common Public License Version 0.5 * * THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF * THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, * REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES * RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. * * 1. DEFINITIONS * * "Contribution" means: * a) in the case of the initial Contributor, the * initial code and documentation distributed under * this Agreement, and * * b) in the case of each subsequent Contributor: * i) changes to the Program, and * ii) additions to the Program; * * where such changes and/or additions to the Program * originate from and are distributed by that * particular Contributor. A Contribution 'originates' * from a Contributor if it was added to the Program * by such Contributor itself or anyone acting on such * Contributor's behalf. Contributions do not include * additions to the Program which: (i) are separate * modules of software distributed in conjunction with * the Program under their own license agreement, and * (ii) are not derivative works of the Program. * * * "Contributor" means any person or entity that distributes * the Program. * * "Licensed Patents " mean patent claims licensable by a * Contributor which are necessarily infringed by the use or * sale of its Contribution alone or when combined with the * Program. * * "Program" means the Contributions distributed in * accordance with this Agreement. * * "Recipient" means anyone who receives the Program under * this Agreement, including all Contributors. * * 2. GRANT OF RIGHTS * * a) Subject to the terms of this Agreement, each * Contributor hereby grants Recipient a * no - exclusive, worldwide, royalt - free copyright * license to reproduce, prepare derivative works of, * publicly display, publicly perform, distribute and * sublicense the Contribution of such Contributor, if * any, and such derivative works, in source code and * object code form. * * b) Subject to the terms of this Agreement, each * Contributor hereby grants Recipient a * no - exclusive, worldwide, royalt - free patent * license under Licensed Patents to make, use, sell, * offer to sell, import and otherwise transfer the * Contribution of such Contributor, if any, in source * code and object code form. This patent license * shall apply to the combination of the Contribution * and the Program if, at the time the Contribution is * added by the Contributor, such addition of the * Contribution causes such combination to be covered * by the Licensed Patents. The patent license shall * not apply to any other combinations which include * the Contribution. No hardware per se is licensed * hereunder. * * c) Recipient understands that although each * Contributor grants the licenses to its * Contributions set forth herein, no assurances are * provided by any Contributor that the Program does * not infringe the patent or other intellectual * property rights of any other entity. Each * Contributor disclaims any liability to Recipient * for claims brought by any other entity based on * infringement of intellectual property rights or * otherwise. As a condition to exercising the rights * and licenses granted hereunder, each Recipient * hereby assumes sole responsibility to secure any * other intellectual property rights needed, if any. * * For example, if a third party patent license is * required to allow Recipient to distribute the * Program, it is Recipient's responsibility to * acquire that license before distributing the * Program. * * d) Each Contributor represents that to its * knowledge it has sufficient copyright rights in its * Contribution, if any, to grant the copyright * license set forth in this Agreement. * * 3. REQUIREMENTS * * A Contributor may choose to distribute the Program in * object code form under its own license agreement, provided * that: * a) it complies with the terms and conditions of * this Agreement; and * * b) its license agreement: * i) effectively disclaims on behalf of all * Contributors all warranties and conditions, express * and implied, including warranties or conditions of * title and no - infringement, and implied warranties * or conditions of merchantability and fitness for a * particular purpose; * * ii) effectively excludes on behalf of all * Contributors all liability for damages, including * direct, indirect, special, incidental and * consequential damages, such as lost profits; * * iii) states that any provisions which differ from * this Agreement are offered by that Contributor * alone and not by any other party; and * * iv) states that source code for the Program is * available from such Contributor, and informs * licensees how to obtain it in a reasonable manner * on or through a medium customarily used for * software exchange. * * When the Program is made available in source code form: * a) it must be made available under this Agreement; * and * b) a copy of this Agreement must be included with * each copy of the Program. * * Contributors may not remove or alter any copyright notices * contained within the Program. * * Each Contributor must identify itself as the originator of * its Contribution, if any, in a manner that reasonably * allows subsequent Recipients to identify the originator of * the Contribution. * * * 4. COMMERCIAL DISTRIBUTION * * Commercial distributors of software may accept certain * responsibilities with respect to end users, business * partners and the like. While this license is intended to * facilitate the commercial use of the Program, the * Contributor who includes the Program in a commercial * product offering should do so in a manner which does not * create potential liability for other Contributors. * Therefore, if a Contributor includes the Program in a * commercial product offering, such Contributor ("Commercial * Contributor") hereby agrees to defend and indemnify every * other Contributor ("Indemnified Contributor") against any * losses, damages and costs (collectively "Losses") arising * from claims, lawsuits and other legal actions brought by a * third party against the Indemnified Contributor to the * extent caused by the acts or omissions of such Commercial * Contributor in connection with its distribution of the * Program in a commercial product offering. The obligations * in this section do not apply to any claims or Losses * relating to any actual or alleged intellectual property * infringement. In order to qualify, an Indemnified * Contributor must: a) promptly notify the Commercial * Contributor in writing of such claim, and b) allow the * Commercial Contributor to control, and cooperate with the * Commercial Contributor in, the defense and any related * settlement negotiations. The Indemnified Contributor may * participate in any such claim at its own expense. * * * For example, a Contributor might include the Program in a * commercial product offering, Product X. That Contributor * is then a Commercial Contributor. If that Commercial * Contributor then makes performance claims, or offers * warranties related to Product X, those performance claims * and warranties are such Commercial Contributor's * responsibility alone. Under this section, the Commercial * Contributor would have to defend claims against the other * Contributors related to those performance claims and * warranties, and if a court requires any other Contributor * to pay any damages as a result, the Commercial Contributor * must pay those damages. * * * 5. NO WARRANTY * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE * PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR * IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR * CONDITIONS OF TITLE, NO - INFRINGEMENT, MERCHANTABILITY OR * FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely * responsible for determining the appropriateness of using * and distributing the Program and assumes all risks * associated with its exercise of rights under this * Agreement, including but not limited to the risks and * costs of program errors, compliance with applicable laws, * damage to or loss of data, programs or equipment, and * unavailability or interruption of operations. * * 6. DISCLAIMER OF LIABILITY * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER * RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION * LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE * OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * 7. GENERAL * * If any provision of this Agreement is invalid or * unenforceable under applicable law, it shall not affect * the validity or enforceability of the remainder of the * terms of this Agreement, and without further action by the * parties hereto, such provision shall be reformed to the * minimum extent necessary to make such provision valid and * enforceable. * * * If Recipient institutes patent litigation against a * Contributor with respect to a patent applicable to * software (including a cros - claim or counterclaim in a * lawsuit), then any patent licenses granted by that * Contributor to such Recipient under this Agreement shall * terminate as of the date such litigation is filed. In * addition, If Recipient institutes patent litigation * against any entity (including a cros - claim or * counterclaim in a lawsuit) alleging that the Program * itself (excluding combinations of the Program with other * software or hardware) infringes such Recipient's * patent(s), then such Recipient's rights granted under * Section 2(b) shall terminate as of the date such * litigation is filed. * * All Recipient's rights under this Agreement shall * terminate if it fails to comply with any of the material * terms or conditions of this Agreement and does not cure * such failure in a reasonable period of time after becoming * aware of such noncompliance. If all Recipient's rights * under this Agreement terminate, Recipient agrees to cease * use and distribution of the Program as soon as reasonably * practicable. However, Recipient's obligations under this * Agreement and any licenses granted by Recipient relating * to the Program shall continue and survive. * * Everyone is permitted to copy and distribute copies of * this Agreement, but in order to avoid inconsistency the * Agreement is copyrighted and may only be modified in the * following manner. The Agreement Steward reserves the right * to publish new versions (including revisions) of this * Agreement from time to time. No one other than the * Agreement Steward has the right to modify this Agreement. * * IBM is the initial Agreement Steward. IBM may assign the * responsibility to serve as the Agreement Steward to a * suitable separate entity. Each new version of the * Agreement will be given a distinguishing version number. * The Program (including Contributions) may always be * distributed subject to the version of the Agreement under * which it was received. In addition, after a new version of * the Agreement is published, Contributor may elect to * distribute the Program (including its Contributions) under * the new version. Except as expressly stated in Sections * 2(a) and 2(b) above, Recipient receives no rights or * licenses to the intellectual property of any Contributor * under this Agreement, whether expressly, by implication, * estoppel or otherwise. All rights in the Program not * expressly granted under this Agreement are reserved. * * * This Agreement is governed by the laws of the State of New * York and the intellectual property laws of the United * States of America. No party to this Agreement will bring a * legal action under this Agreement more than one year after * the cause of action arose. Each party waives its rights to * a jury trial in any resulting litigation. * * * * (C) COPYRIGHT International Business Machines Corp. 2001, 2002 */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include "tpmtok_int.h" CK_RV key_object_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode) { CK_ATTRIBUTE * attr = NULL; CK_BBOOL found; found = template_attribute_find(tmpl, CKA_KEY_TYPE, &attr); if (! found) { if (mode == MODE_CREATE) { return (CKR_TEMPLATE_INCOMPLETE); } } return (template_check_required_base_attributes(tmpl, mode)); } CK_RV key_object_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode) { CK_ATTRIBUTE * id_attr = NULL; CK_ATTRIBUTE * sdate_attr = NULL; CK_ATTRIBUTE * edate_attr = NULL; CK_ATTRIBUTE * derive_attr = NULL; CK_ATTRIBUTE * local_attr = NULL; // satisfy the compiler // if (mode) id_attr = NULL; id_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE)); sdate_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE)); edate_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE)); derive_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + sizeof (CK_BBOOL)); local_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + sizeof (CK_BBOOL)); if (! id_attr || ! sdate_attr || ! edate_attr || ! derive_attr || ! local_attr) { if (id_attr) free(id_attr); if (sdate_attr) free(sdate_attr); if (edate_attr) free(edate_attr); if (derive_attr) free(derive_attr); if (local_attr) free(local_attr); return (CKR_HOST_MEMORY); } id_attr->type = CKA_ID; id_attr->ulValueLen = 0; id_attr->pValue = NULL; sdate_attr->type = CKA_START_DATE; sdate_attr->ulValueLen = 0; sdate_attr->pValue = NULL; edate_attr->type = CKA_END_DATE; edate_attr->ulValueLen = 0; edate_attr->pValue = NULL; derive_attr->type = CKA_DERIVE; derive_attr->ulValueLen = sizeof (CK_BBOOL); derive_attr->pValue = (CK_BYTE *)derive_attr + sizeof (CK_ATTRIBUTE); *(CK_BBOOL *)derive_attr->pValue = FALSE; local_attr->type = CKA_LOCAL; local_attr->ulValueLen = sizeof (CK_BBOOL); local_attr->pValue = (CK_BYTE *)local_attr + sizeof (CK_ATTRIBUTE); *(CK_BBOOL *)local_attr->pValue = FALSE; (void) template_update_attribute(tmpl, id_attr); (void) template_update_attribute(tmpl, sdate_attr); (void) template_update_attribute(tmpl, edate_attr); (void) template_update_attribute(tmpl, derive_attr); (void) template_update_attribute(tmpl, local_attr); return (CKR_OK); } CK_RV key_object_validate_attribute(TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode) { switch (attr->type) { case CKA_KEY_TYPE: if (mode == MODE_CREATE || mode == MODE_DERIVE || mode == MODE_KEYGEN || mode == MODE_UNWRAP) return (CKR_OK); else { return (CKR_ATTRIBUTE_READ_ONLY); } case CKA_ID: case CKA_START_DATE: case CKA_END_DATE: case CKA_DERIVE: return (CKR_OK); case CKA_LOCAL: return (CKR_ATTRIBUTE_READ_ONLY); default: return (template_validate_base_attribute(tmpl, attr, mode)); } } CK_RV publ_key_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode) { return (key_object_check_required_attributes(tmpl, mode)); } CK_RV publ_key_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode) { CK_ATTRIBUTE *class_attr = NULL; CK_ATTRIBUTE *subject_attr = NULL; CK_ATTRIBUTE *encrypt_attr = NULL; CK_ATTRIBUTE *verify_attr = NULL; CK_ATTRIBUTE *verify_recover_attr = NULL; CK_ATTRIBUTE *wrap_attr = NULL; CK_OBJECT_CLASS class = CKO_PUBLIC_KEY; CK_RV rc; rc = key_object_set_default_attributes(tmpl, mode); if (rc != CKR_OK) { return (rc); } // // add the default CKO_PUBLIC_KEY attributes // class_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + sizeof (CK_OBJECT_CLASS)); subject_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE)); encrypt_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + sizeof (CK_BBOOL)); verify_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + sizeof (CK_BBOOL)); verify_recover_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + sizeof (CK_BBOOL)); wrap_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + sizeof (CK_BBOOL)); if (! class || ! subject_attr || ! encrypt_attr || ! verify_attr || ! verify_recover_attr || ! wrap_attr) { if (class_attr) free(class_attr); if (subject_attr) free(subject_attr); if (encrypt_attr) free(encrypt_attr); if (verify_attr) free(verify_attr); if (verify_recover_attr) free(verify_recover_attr); if (wrap_attr) free(wrap_attr); return (CKR_HOST_MEMORY); } class_attr->type = CKA_CLASS; class_attr->ulValueLen = sizeof (CK_OBJECT_CLASS); class_attr->pValue = (CK_BYTE *)class_attr + sizeof (CK_ATTRIBUTE); *(CK_OBJECT_CLASS *)class_attr->pValue = CKO_PUBLIC_KEY; subject_attr->type = CKA_SUBJECT; subject_attr->ulValueLen = 0; // empty string subject_attr->pValue = NULL; encrypt_attr->type = CKA_ENCRYPT; encrypt_attr->ulValueLen = sizeof (CK_BBOOL); encrypt_attr->pValue = (CK_BYTE *)encrypt_attr + sizeof (CK_ATTRIBUTE); *(CK_BBOOL *)encrypt_attr->pValue = TRUE; verify_attr->type = CKA_VERIFY; verify_attr->ulValueLen = sizeof (CK_BBOOL); verify_attr->pValue = (CK_BYTE *)verify_attr + sizeof (CK_ATTRIBUTE); *(CK_BBOOL *)verify_attr->pValue = TRUE; verify_recover_attr->type = CKA_VERIFY_RECOVER; verify_recover_attr->ulValueLen = sizeof (CK_BBOOL); verify_recover_attr->pValue = (CK_BYTE *)verify_recover_attr + sizeof (CK_ATTRIBUTE); *(CK_BBOOL *)verify_recover_attr->pValue = TRUE; wrap_attr->type = CKA_WRAP; wrap_attr->ulValueLen = sizeof (CK_BBOOL); wrap_attr->pValue = (CK_BYTE *)wrap_attr + sizeof (CK_ATTRIBUTE); *(CK_BBOOL *)wrap_attr->pValue = TRUE; (void) template_update_attribute(tmpl, class_attr); (void) template_update_attribute(tmpl, subject_attr); (void) template_update_attribute(tmpl, encrypt_attr); (void) template_update_attribute(tmpl, verify_attr); (void) template_update_attribute(tmpl, verify_recover_attr); (void) template_update_attribute(tmpl, wrap_attr); return (CKR_OK); } CK_RV publ_key_validate_attribute(TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode) { switch (attr->type) { case CKA_SUBJECT: return (CKR_OK); case CKA_ENCRYPT: case CKA_VERIFY: case CKA_VERIFY_RECOVER: case CKA_WRAP: if (mode == MODE_MODIFY) { if (nv_token_data->tweak_vector.allow_key_mods == TRUE) return (CKR_OK); return (CKR_ATTRIBUTE_READ_ONLY); } return (CKR_OK); default: return (key_object_validate_attribute(tmpl, attr, mode)); } } CK_RV priv_key_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode) { return (key_object_check_required_attributes(tmpl, mode)); } CK_RV priv_key_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode) { CK_ATTRIBUTE *class_attr = NULL; CK_ATTRIBUTE *subject_attr = NULL; CK_ATTRIBUTE *sensitive_attr = NULL; CK_ATTRIBUTE *decrypt_attr = NULL; CK_ATTRIBUTE *sign_attr = NULL; CK_ATTRIBUTE *sign_recover_attr = NULL; CK_ATTRIBUTE *unwrap_attr = NULL; CK_ATTRIBUTE *extractable_attr = NULL; CK_ATTRIBUTE *never_extr_attr = NULL; CK_ATTRIBUTE *always_sens_attr = NULL; CK_RV rc; rc = key_object_set_default_attributes(tmpl, mode); if (rc != CKR_OK) { return (rc); } class_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + sizeof (CK_OBJECT_CLASS)); subject_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE)); sensitive_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + sizeof (CK_BBOOL)); decrypt_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + sizeof (CK_BBOOL)); sign_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + sizeof (CK_BBOOL)); sign_recover_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + sizeof (CK_BBOOL)); unwrap_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + sizeof (CK_BBOOL)); extractable_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + sizeof (CK_BBOOL)); never_extr_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + sizeof (CK_BBOOL)); always_sens_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + sizeof (CK_BBOOL)); if (! class_attr || ! subject_attr || ! sensitive_attr || ! decrypt_attr || ! sign_attr || ! sign_recover_attr || ! unwrap_attr || ! extractable_attr || ! never_extr_attr || ! always_sens_attr) { if (class_attr) free(class_attr); if (subject_attr) free(subject_attr); if (sensitive_attr) free(sensitive_attr); if (decrypt_attr) free(decrypt_attr); if (sign_attr) free(sign_attr); if (sign_recover_attr) free(sign_recover_attr); if (unwrap_attr) free(unwrap_attr); if (extractable_attr) free(extractable_attr); if (always_sens_attr) free(always_sens_attr); if (never_extr_attr) free(never_extr_attr); return (CKR_HOST_MEMORY); } class_attr->type = CKA_CLASS; class_attr->ulValueLen = sizeof (CK_OBJECT_CLASS); class_attr->pValue = (CK_BYTE *)class_attr + sizeof (CK_ATTRIBUTE); *(CK_OBJECT_CLASS *)class_attr->pValue = CKO_PRIVATE_KEY; subject_attr->type = CKA_SUBJECT; subject_attr->ulValueLen = 0; // empty string subject_attr->pValue = NULL; sensitive_attr->type = CKA_SENSITIVE; sensitive_attr->ulValueLen = sizeof (CK_BBOOL); sensitive_attr->pValue = (CK_BYTE *)sensitive_attr + sizeof (CK_ATTRIBUTE); *(CK_BBOOL *)sensitive_attr->pValue = FALSE; decrypt_attr->type = CKA_DECRYPT; decrypt_attr->ulValueLen = sizeof (CK_BBOOL); decrypt_attr->pValue = (CK_BYTE *)decrypt_attr + sizeof (CK_ATTRIBUTE); *(CK_BBOOL *)decrypt_attr->pValue = TRUE; sign_attr->type = CKA_SIGN; sign_attr->ulValueLen = sizeof (CK_BBOOL); sign_attr->pValue = (CK_BYTE *)sign_attr + sizeof (CK_ATTRIBUTE); *(CK_BBOOL *)sign_attr->pValue = TRUE; sign_recover_attr->type = CKA_SIGN_RECOVER; sign_recover_attr->ulValueLen = sizeof (CK_BBOOL); sign_recover_attr->pValue = (CK_BYTE *)sign_recover_attr + sizeof (CK_ATTRIBUTE); *(CK_BBOOL *)sign_recover_attr->pValue = TRUE; unwrap_attr->type = CKA_UNWRAP; unwrap_attr->ulValueLen = sizeof (CK_BBOOL); unwrap_attr->pValue = (CK_BYTE *)unwrap_attr + sizeof (CK_ATTRIBUTE); *(CK_BBOOL *)unwrap_attr->pValue = TRUE; extractable_attr->type = CKA_EXTRACTABLE; extractable_attr->ulValueLen = sizeof (CK_BBOOL); extractable_attr->pValue = (CK_BYTE *)extractable_attr + sizeof (CK_ATTRIBUTE); *(CK_BBOOL *)extractable_attr->pValue = TRUE; never_extr_attr->type = CKA_NEVER_EXTRACTABLE; never_extr_attr->ulValueLen = sizeof (CK_BBOOL); never_extr_attr->pValue = (CK_BYTE *)never_extr_attr + sizeof (CK_ATTRIBUTE); *(CK_BBOOL *)never_extr_attr->pValue = FALSE; always_sens_attr->type = CKA_ALWAYS_SENSITIVE; always_sens_attr->ulValueLen = sizeof (CK_BBOOL); always_sens_attr->pValue = (CK_BYTE *)always_sens_attr + sizeof (CK_ATTRIBUTE); *(CK_BBOOL *)always_sens_attr->pValue = FALSE; (void) template_update_attribute(tmpl, class_attr); (void) template_update_attribute(tmpl, subject_attr); (void) template_update_attribute(tmpl, sensitive_attr); (void) template_update_attribute(tmpl, decrypt_attr); (void) template_update_attribute(tmpl, sign_attr); (void) template_update_attribute(tmpl, sign_recover_attr); (void) template_update_attribute(tmpl, unwrap_attr); (void) template_update_attribute(tmpl, extractable_attr); (void) template_update_attribute(tmpl, never_extr_attr); (void) template_update_attribute(tmpl, always_sens_attr); return (CKR_OK); } CK_RV priv_key_unwrap(TEMPLATE *tmpl, CK_ULONG keytype, CK_BYTE *data, CK_ULONG data_len) { CK_ATTRIBUTE *extractable = NULL; CK_ATTRIBUTE *always_sens = NULL; CK_ATTRIBUTE *never_extract = NULL; CK_ATTRIBUTE *sensitive = NULL; CK_ATTRIBUTE *local = NULL; CK_BBOOL true = TRUE; CK_BBOOL false = FALSE; CK_RV rc; switch (keytype) { case CKK_RSA: rc = rsa_priv_unwrap(tmpl, data, data_len); break; default: return (CKR_WRAPPED_KEY_INVALID); } if (rc != CKR_OK) { return (rc); } /* * make sure * CKA_LOCAL == FALSE * CKA_ALWAYS_SENSITIVE == FALSE * CKA_EXTRACTABLE == TRUE * CKA_NEVER_EXTRACTABLE == FALSE */ rc = build_attribute(CKA_LOCAL, &false, 1, &local); if (rc != CKR_OK) { goto cleanup; } rc = build_attribute(CKA_ALWAYS_SENSITIVE, &false, 1, &always_sens); if (rc != CKR_OK) { goto cleanup; } rc = build_attribute(CKA_SENSITIVE, &false, 1, &sensitive); if (rc != CKR_OK) { goto cleanup; } rc = build_attribute(CKA_EXTRACTABLE, &true, 1, &extractable); if (rc != CKR_OK) { goto cleanup; } rc = build_attribute(CKA_NEVER_EXTRACTABLE, &false, 1, &never_extract); if (rc != CKR_OK) { goto cleanup; } (void) template_update_attribute(tmpl, local); (void) template_update_attribute(tmpl, always_sens); (void) template_update_attribute(tmpl, sensitive); (void) template_update_attribute(tmpl, extractable); (void) template_update_attribute(tmpl, never_extract); return (CKR_OK); cleanup: if (local) free(local); if (always_sens) free(always_sens); if (extractable) free(extractable); if (never_extract) free(never_extract); return (rc); } CK_RV priv_key_validate_attribute(TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode) { switch (attr->type) { case CKA_SUBJECT: return (CKR_OK); case CKA_DECRYPT: case CKA_SIGN: case CKA_SIGN_RECOVER: case CKA_UNWRAP: // we might want to do this for MODE_COPY too // if (mode == MODE_MODIFY) { if (nv_token_data->tweak_vector.allow_key_mods == TRUE) return (CKR_OK); return (CKR_ATTRIBUTE_READ_ONLY); } return (CKR_OK); // after key creation, CKA_SENSITIVE may only be set to TRUE // case CKA_SENSITIVE: { CK_BBOOL value; if (mode == MODE_CREATE || mode == MODE_KEYGEN) return (CKR_OK); value = *(CK_BBOOL *)attr->pValue; if (value != TRUE) { return (CKR_ATTRIBUTE_READ_ONLY); } } return (CKR_OK); case CKA_EXTRACTABLE: { CK_BBOOL value; value = *(CK_BBOOL *)attr->pValue; if ((mode != MODE_CREATE && mode != MODE_KEYGEN) && value != FALSE) { return (CKR_ATTRIBUTE_READ_ONLY); } if (value == FALSE) { CK_ATTRIBUTE *attr; attr = (CK_ATTRIBUTE *)malloc( sizeof (CK_ATTRIBUTE) + sizeof (CK_BBOOL)); if (! attr) { return (CKR_HOST_MEMORY); } attr->type = CKA_NEVER_EXTRACTABLE; attr->ulValueLen = sizeof (CK_BBOOL); attr->pValue = (CK_BYTE *)attr + sizeof (CK_ATTRIBUTE); *(CK_BBOOL *)attr->pValue = FALSE; (void) template_update_attribute(tmpl, attr); } } return (CKR_OK); case CKA_ALWAYS_SENSITIVE: case CKA_NEVER_EXTRACTABLE: return (CKR_ATTRIBUTE_READ_ONLY); default: return (key_object_validate_attribute(tmpl, attr, mode)); } } CK_RV secret_key_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode) { return (key_object_check_required_attributes(tmpl, mode)); } CK_RV secret_key_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode) { CK_ATTRIBUTE *class_attr = NULL; CK_ATTRIBUTE *sensitive_attr = NULL; CK_ATTRIBUTE *encrypt_attr = NULL; CK_ATTRIBUTE *decrypt_attr = NULL; CK_ATTRIBUTE *sign_attr = NULL; CK_ATTRIBUTE *verify_attr = NULL; CK_ATTRIBUTE *wrap_attr = NULL; CK_ATTRIBUTE *unwrap_attr = NULL; CK_ATTRIBUTE *extractable_attr = NULL; CK_ATTRIBUTE *never_extr_attr = NULL; CK_ATTRIBUTE *always_sens_attr = NULL; CK_RV rc; rc = key_object_set_default_attributes(tmpl, mode); if (rc != CKR_OK) return (rc); class_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + sizeof (CK_OBJECT_CLASS)); sensitive_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + sizeof (CK_BBOOL)); encrypt_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + sizeof (CK_BBOOL)); decrypt_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + sizeof (CK_BBOOL)); sign_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + sizeof (CK_BBOOL)); verify_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + sizeof (CK_BBOOL)); wrap_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + sizeof (CK_BBOOL)); unwrap_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + sizeof (CK_BBOOL)); extractable_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + sizeof (CK_BBOOL)); never_extr_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + sizeof (CK_BBOOL)); always_sens_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + sizeof (CK_BBOOL)); if (! class_attr || ! sensitive_attr || ! encrypt_attr || ! decrypt_attr || ! sign_attr || ! verify_attr || ! wrap_attr || ! unwrap_attr || ! extractable_attr || ! never_extr_attr || ! always_sens_attr) { if (class_attr) free(class_attr); if (sensitive_attr) free(sensitive_attr); if (encrypt_attr) free(encrypt_attr); if (decrypt_attr) free(decrypt_attr); if (sign_attr) free(sign_attr); if (verify_attr) free(verify_attr); if (wrap_attr) free(wrap_attr); if (unwrap_attr) free(unwrap_attr); if (extractable_attr) free(extractable_attr); if (never_extr_attr) free(never_extr_attr); if (always_sens_attr) free(always_sens_attr); return (CKR_HOST_MEMORY); } class_attr->type = CKA_CLASS; class_attr->ulValueLen = sizeof (CK_OBJECT_CLASS); class_attr->pValue = (CK_BYTE *)class_attr + sizeof (CK_ATTRIBUTE); *(CK_OBJECT_CLASS *)class_attr->pValue = CKO_SECRET_KEY; sensitive_attr->type = CKA_SENSITIVE; sensitive_attr->ulValueLen = sizeof (CK_BBOOL); sensitive_attr->pValue = (CK_BYTE *)sensitive_attr + sizeof (CK_ATTRIBUTE); *(CK_BBOOL *)sensitive_attr->pValue = FALSE; encrypt_attr->type = CKA_ENCRYPT; encrypt_attr->ulValueLen = sizeof (CK_BBOOL); encrypt_attr->pValue = (CK_BYTE *)encrypt_attr + sizeof (CK_ATTRIBUTE); *(CK_BBOOL *)encrypt_attr->pValue = TRUE; decrypt_attr->type = CKA_DECRYPT; decrypt_attr->ulValueLen = sizeof (CK_BBOOL); decrypt_attr->pValue = (CK_BYTE *)decrypt_attr + sizeof (CK_ATTRIBUTE); *(CK_BBOOL *)decrypt_attr->pValue = TRUE; sign_attr->type = CKA_SIGN; sign_attr->ulValueLen = sizeof (CK_BBOOL); sign_attr->pValue = (CK_BYTE *)sign_attr + sizeof (CK_ATTRIBUTE); *(CK_BBOOL *)sign_attr->pValue = TRUE; verify_attr->type = CKA_VERIFY; verify_attr->ulValueLen = sizeof (CK_BBOOL); verify_attr->pValue = (CK_BYTE *)verify_attr + sizeof (CK_ATTRIBUTE); *(CK_BBOOL *)verify_attr->pValue = TRUE; wrap_attr->type = CKA_WRAP; wrap_attr->ulValueLen = sizeof (CK_BBOOL); wrap_attr->pValue = (CK_BYTE *)wrap_attr + sizeof (CK_ATTRIBUTE); *(CK_BBOOL *)wrap_attr->pValue = TRUE; unwrap_attr->type = CKA_UNWRAP; unwrap_attr->ulValueLen = sizeof (CK_BBOOL); unwrap_attr->pValue = (CK_BYTE *)unwrap_attr + sizeof (CK_ATTRIBUTE); *(CK_BBOOL *)unwrap_attr->pValue = TRUE; extractable_attr->type = CKA_EXTRACTABLE; extractable_attr->ulValueLen = sizeof (CK_BBOOL); extractable_attr->pValue = (CK_BYTE *)extractable_attr + sizeof (CK_ATTRIBUTE); *(CK_BBOOL *)extractable_attr->pValue = TRUE; always_sens_attr->type = CKA_ALWAYS_SENSITIVE; always_sens_attr->ulValueLen = sizeof (CK_BBOOL); always_sens_attr->pValue = (CK_BYTE *)always_sens_attr + sizeof (CK_ATTRIBUTE); *(CK_BBOOL *)always_sens_attr->pValue = FALSE; never_extr_attr->type = CKA_NEVER_EXTRACTABLE; never_extr_attr->ulValueLen = sizeof (CK_BBOOL); never_extr_attr->pValue = (CK_BYTE *)never_extr_attr + sizeof (CK_ATTRIBUTE); *(CK_BBOOL *)never_extr_attr->pValue = FALSE; (void) template_update_attribute(tmpl, class_attr); (void) template_update_attribute(tmpl, sensitive_attr); (void) template_update_attribute(tmpl, encrypt_attr); (void) template_update_attribute(tmpl, decrypt_attr); (void) template_update_attribute(tmpl, sign_attr); (void) template_update_attribute(tmpl, verify_attr); (void) template_update_attribute(tmpl, wrap_attr); (void) template_update_attribute(tmpl, unwrap_attr); (void) template_update_attribute(tmpl, extractable_attr); (void) template_update_attribute(tmpl, never_extr_attr); (void) template_update_attribute(tmpl, always_sens_attr); return (CKR_OK); } CK_RV secret_key_unwrap(TEMPLATE *tmpl, CK_ULONG keytype, CK_BYTE *data, CK_ULONG data_len, CK_BBOOL fromend) { CK_ATTRIBUTE *local = NULL; CK_ATTRIBUTE *always_sens = NULL; CK_ATTRIBUTE *sensitive = NULL; CK_ATTRIBUTE *extractable = NULL; CK_ATTRIBUTE *never_extract = NULL; CK_BBOOL true = TRUE; CK_BBOOL false = FALSE; CK_RV rc; switch (keytype) { case CKK_GENERIC_SECRET: rc = generic_secret_unwrap(tmpl, data, data_len, fromend); break; default: return (CKR_WRAPPED_KEY_INVALID); } if (rc != CKR_OK) return (rc); // make sure // CKA_LOCAL == FALSE // CKA_ALWAYS_SENSITIVE == FALSE // CKA_EXTRACTABLE == TRUE // CKA_NEVER_EXTRACTABLE == FALSE // rc = build_attribute(CKA_LOCAL, &false, 1, &local); if (rc != CKR_OK) { goto cleanup; } rc = build_attribute(CKA_ALWAYS_SENSITIVE, &false, 1, &always_sens); if (rc != CKR_OK) { goto cleanup; } rc = build_attribute(CKA_SENSITIVE, &false, 1, &sensitive); if (rc != CKR_OK) { goto cleanup; } rc = build_attribute(CKA_EXTRACTABLE, &true, 1, &extractable); if (rc != CKR_OK) { goto cleanup; } rc = build_attribute(CKA_NEVER_EXTRACTABLE, &false, 1, &never_extract); if (rc != CKR_OK) { goto cleanup; } (void) template_update_attribute(tmpl, local); (void) template_update_attribute(tmpl, always_sens); (void) template_update_attribute(tmpl, sensitive); (void) template_update_attribute(tmpl, extractable); (void) template_update_attribute(tmpl, never_extract); return (CKR_OK); cleanup: if (local) free(local); if (extractable) free(extractable); if (always_sens) free(always_sens); if (never_extract) free(never_extract); return (rc); } CK_RV secret_key_validate_attribute(TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode) { switch (attr->type) { case CKA_ENCRYPT: case CKA_DECRYPT: case CKA_SIGN: case CKA_VERIFY: case CKA_WRAP: case CKA_UNWRAP: if (mode == MODE_MODIFY) { if (nv_token_data->tweak_vector.allow_key_mods == TRUE) return (CKR_OK); return (CKR_ATTRIBUTE_READ_ONLY); } return (CKR_OK); // after key creation, CKA_SENSITIVE may only be set to TRUE // case CKA_SENSITIVE: { CK_BBOOL value; value = *(CK_BBOOL *)attr->pValue; if ((mode != MODE_CREATE && mode != MODE_DERIVE && mode != MODE_KEYGEN) && (value != TRUE)) { return (CKR_ATTRIBUTE_READ_ONLY); } } return (CKR_OK); case CKA_EXTRACTABLE: { CK_BBOOL value; value = *(CK_BBOOL *)attr->pValue; if ((mode != MODE_CREATE && mode != MODE_DERIVE && mode != MODE_KEYGEN) && (value != FALSE)) { return (CKR_ATTRIBUTE_READ_ONLY); } if (value == FALSE) { CK_ATTRIBUTE *attr; attr = (CK_ATTRIBUTE *)malloc( sizeof (CK_ATTRIBUTE) + sizeof (CK_BBOOL)); if (! attr) { return (CKR_HOST_MEMORY); } attr->type = CKA_NEVER_EXTRACTABLE; attr->ulValueLen = sizeof (CK_BBOOL); attr->pValue = (CK_BYTE *)attr + sizeof (CK_ATTRIBUTE); *(CK_BBOOL *)attr->pValue = FALSE; (void) template_update_attribute(tmpl, attr); } } return (CKR_OK); case CKA_ALWAYS_SENSITIVE: case CKA_NEVER_EXTRACTABLE: return (CKR_ATTRIBUTE_READ_ONLY); default: return (key_object_validate_attribute(tmpl, attr, mode)); } } CK_BBOOL secret_key_check_exportability(CK_ATTRIBUTE_TYPE type) { switch (type) { case CKA_VALUE: return (FALSE); } return (TRUE); } CK_RV rsa_publ_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL found; found = template_attribute_find(tmpl, CKA_MODULUS, &attr); if (! found) { if (mode == MODE_CREATE) { return (CKR_TEMPLATE_INCOMPLETE); } } found = template_attribute_find(tmpl, CKA_MODULUS_BITS, &attr); if (! found) { if (mode == MODE_KEYGEN) { return (CKR_TEMPLATE_INCOMPLETE); } } found = template_attribute_find(tmpl, CKA_PUBLIC_EXPONENT, &attr); if (! found) { if (mode == MODE_CREATE || mode == MODE_KEYGEN) { return (CKR_TEMPLATE_INCOMPLETE); } } return (publ_key_check_required_attributes(tmpl, mode)); } CK_RV rsa_publ_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode) { CK_ATTRIBUTE *type_attr = NULL; CK_ATTRIBUTE *modulus_attr = NULL; CK_ATTRIBUTE *modulus_bits_attr = NULL; CK_ATTRIBUTE *public_exp_attr = NULL; CK_ULONG bits = 0L; (void) publ_key_set_default_attributes(tmpl, mode); type_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + sizeof (CK_KEY_TYPE)); modulus_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE)); modulus_bits_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + sizeof (CK_ULONG)); public_exp_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE)); if (! type_attr || ! modulus_attr || ! modulus_bits_attr || ! public_exp_attr) { if (type_attr) free(type_attr); if (modulus_attr) free(modulus_attr); if (modulus_bits_attr) free(modulus_bits_attr); if (public_exp_attr) free(public_exp_attr); return (CKR_HOST_MEMORY); } type_attr->type = CKA_KEY_TYPE; type_attr->ulValueLen = sizeof (CK_KEY_TYPE); type_attr->pValue = (CK_BYTE *)type_attr + sizeof (CK_ATTRIBUTE); *(CK_KEY_TYPE *)type_attr->pValue = CKK_RSA; modulus_attr->type = CKA_MODULUS; modulus_attr->ulValueLen = 0; modulus_attr->pValue = NULL; modulus_bits_attr->type = CKA_MODULUS_BITS; modulus_bits_attr->ulValueLen = sizeof (CK_ULONG); modulus_bits_attr->pValue = (CK_BYTE *)modulus_bits_attr + sizeof (CK_ATTRIBUTE); *(CK_ULONG *)modulus_bits_attr->pValue = bits; public_exp_attr->type = CKA_PUBLIC_EXPONENT; public_exp_attr->ulValueLen = 0; public_exp_attr->pValue = NULL; (void) template_update_attribute(tmpl, type_attr); (void) template_update_attribute(tmpl, modulus_attr); (void) template_update_attribute(tmpl, modulus_bits_attr); (void) template_update_attribute(tmpl, public_exp_attr); return (CKR_OK); } CK_RV rsa_publ_validate_attribute(TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode) { switch (attr->type) { case CKA_MODULUS_BITS: if (mode == MODE_KEYGEN) { if (attr->ulValueLen != sizeof (CK_ULONG)) { return (CKR_ATTRIBUTE_VALUE_INVALID); } else { CK_ULONG mod_bits = *(CK_ULONG *)attr->pValue; if (mod_bits < 512 || mod_bits > 2048) { return (CKR_ATTRIBUTE_VALUE_INVALID); } if (mod_bits % 8 != 0) { return (CKR_ATTRIBUTE_VALUE_INVALID); } return (CKR_OK); } } else { return (CKR_ATTRIBUTE_READ_ONLY); } case CKA_MODULUS: if (mode == MODE_CREATE) return (remove_leading_zeros(attr)); else { return (CKR_ATTRIBUTE_READ_ONLY); } case CKA_PUBLIC_EXPONENT: if (mode == MODE_CREATE || mode == MODE_KEYGEN) return (remove_leading_zeros(attr)); else { return (CKR_ATTRIBUTE_READ_ONLY); } default: return (publ_key_validate_attribute(tmpl, attr, mode)); } } CK_RV rsa_priv_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL found; found = template_attribute_find(tmpl, CKA_MODULUS, &attr); if (! found) { if (mode == MODE_CREATE) { return (CKR_TEMPLATE_INCOMPLETE); } } // // PKCS #11 is flexible with respect to which attributes must be present // in an RSA key. Keys can be specified in Chinese Remainder format or // they can be specified in modula exponent format. Right now, I only // support keys created in Chinese Remainder format. That is, we return // CKR_TEMPLATE_INCOMPLETE if a modula exponent key is specified. This // is allowed by PKCS #11. // // In the future, we should allow for creation of keys in modula exp // format too. This raises some issues. It's easy enough to recognize // when a key has been specified in modula exponent format. And it's // easy enough to recognize when all attributes have been specified // (which is what we require right now). What's trickier to handle is // the "middle" cases in which more than the minimum yet less than the // full number of attributes have been specified. Do we revert back to // modula - exponent representation? Do we compute the missing // attributes ourselves? Do we simply return CKR_TEMPLATE_INCOMPLETE? // found = template_attribute_find(tmpl, CKA_PUBLIC_EXPONENT, &attr); if (! found) { if (mode == MODE_CREATE) { return (CKR_TEMPLATE_INCOMPLETE); } } found = template_attribute_find(tmpl, CKA_PRIVATE_EXPONENT, &attr); if (! found) { if (mode == MODE_CREATE) { return (CKR_TEMPLATE_INCOMPLETE); } } found = template_attribute_find(tmpl, CKA_PRIME_1, &attr); if (! found) { if (mode == MODE_CREATE) { return (CKR_TEMPLATE_INCOMPLETE); } } found = template_attribute_find(tmpl, CKA_PRIME_2, &attr); if (! found) { if (mode == MODE_CREATE) { return (CKR_TEMPLATE_INCOMPLETE); } } found = template_attribute_find(tmpl, CKA_EXPONENT_1, &attr); if (! found) { if (mode == MODE_CREATE) { return (CKR_TEMPLATE_INCOMPLETE); } } found = template_attribute_find(tmpl, CKA_EXPONENT_2, &attr); if (! found) { if (mode == MODE_CREATE) { return (CKR_TEMPLATE_INCOMPLETE); } } found = template_attribute_find(tmpl, CKA_COEFFICIENT, &attr); if (! found) { if (mode == MODE_CREATE) { return (CKR_TEMPLATE_INCOMPLETE); } } return (priv_key_check_required_attributes(tmpl, mode)); } CK_RV rsa_priv_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode) { CK_ATTRIBUTE *modulus_attr = NULL; CK_ATTRIBUTE *public_exp_attr = NULL; CK_ATTRIBUTE *private_exp_attr = NULL; CK_ATTRIBUTE *type_attr = NULL; (void) priv_key_set_default_attributes(tmpl, mode); type_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + sizeof (CK_KEY_TYPE)); modulus_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE)); public_exp_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE)); private_exp_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE)); if (! type_attr || ! modulus_attr || ! public_exp_attr || ! private_exp_attr) { if (type_attr) free(type_attr); if (modulus_attr) free(modulus_attr); if (public_exp_attr) free(public_exp_attr); if (private_exp_attr) free(private_exp_attr); return (CKR_HOST_MEMORY); } modulus_attr->type = CKA_MODULUS; modulus_attr->ulValueLen = 0; modulus_attr->pValue = NULL; public_exp_attr->type = CKA_PUBLIC_EXPONENT; public_exp_attr->ulValueLen = 0; public_exp_attr->pValue = NULL; private_exp_attr->type = CKA_PRIVATE_EXPONENT; private_exp_attr->ulValueLen = 0; private_exp_attr->pValue = NULL; type_attr->type = CKA_KEY_TYPE; type_attr->ulValueLen = sizeof (CK_KEY_TYPE); type_attr->pValue = (CK_BYTE *)type_attr + sizeof (CK_ATTRIBUTE); *(CK_KEY_TYPE *)type_attr->pValue = CKK_RSA; (void) template_update_attribute(tmpl, type_attr); (void) template_update_attribute(tmpl, modulus_attr); (void) template_update_attribute(tmpl, public_exp_attr); (void) template_update_attribute(tmpl, private_exp_attr); return (CKR_OK); } CK_RV rsa_priv_validate_attribute(TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode) { switch (attr->type) { case CKA_MODULUS: case CKA_PRIVATE_EXPONENT: if (mode == MODE_CREATE) return (remove_leading_zeros(attr)); else { return (CKR_ATTRIBUTE_READ_ONLY); } case CKA_PUBLIC_EXPONENT: case CKA_PRIME_1: case CKA_PRIME_2: case CKA_EXPONENT_1: case CKA_EXPONENT_2: case CKA_COEFFICIENT: if (mode == MODE_CREATE) return (remove_leading_zeros(attr)); else { return (CKR_ATTRIBUTE_READ_ONLY); } default: return (priv_key_validate_attribute(tmpl, attr, mode)); } } CK_BBOOL rsa_priv_check_exportability(CK_ATTRIBUTE_TYPE type) { switch (type) { case CKA_PRIVATE_EXPONENT: case CKA_PRIME_1: case CKA_PRIME_2: case CKA_EXPONENT_1: case CKA_EXPONENT_2: case CKA_COEFFICIENT: return (FALSE); } return (TRUE); } /* * create the ASN.1 encoding for the private key for wrapping as defined * in PKCS #8 * * ASN.1 type PrivateKeyInfo ::= SEQUENCE { * version Version * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier * privateKey PrivateKey * attributes OPTIONAL * * } * * Where PrivateKey is defined as follows for RSA: * * ASN.1 type RSAPrivateKey * * RSAPrivateKey ::= SEQUENCE { * version Version * modulus INTEGER * publicExponent INTEGER * privateExponent INTEGER * prime1 INTEGER * prime2 INTEGER * exponent1 INTEGER * exponent2 INTEGER * coefficient INTEGER * } */ CK_RV rsa_priv_wrap_get_data(TEMPLATE *tmpl, CK_BBOOL length_only, CK_BYTE **data, CK_ULONG *data_len) { CK_ATTRIBUTE *modulus = NULL; CK_ATTRIBUTE *publ_exp = NULL, *priv_exp = NULL; CK_ATTRIBUTE *prime1 = NULL, *prime2 = NULL; CK_ATTRIBUTE *exponent1 = NULL, *exponent2 = NULL; CK_ATTRIBUTE *coeff = NULL; CK_RV rc; if (template_attribute_find(tmpl, CKA_MODULUS, &modulus) == FALSE) { return (CKR_FUNCTION_FAILED); } if (template_attribute_find(tmpl, CKA_PUBLIC_EXPONENT, &publ_exp) == FALSE) { return (CKR_FUNCTION_FAILED); } if (template_attribute_find(tmpl, CKA_PRIVATE_EXPONENT, &priv_exp) == FALSE) { return (CKR_FUNCTION_FAILED); } if (template_attribute_find(tmpl, CKA_PRIME_1, &prime1) == FALSE) { return (CKR_FUNCTION_FAILED); } if (template_attribute_find(tmpl, CKA_PRIME_2, &prime2) == FALSE) { return (CKR_FUNCTION_FAILED); } if (template_attribute_find(tmpl, CKA_EXPONENT_1, &exponent1) == FALSE) { return (CKR_FUNCTION_FAILED); } if (template_attribute_find(tmpl, CKA_EXPONENT_2, &exponent2) == FALSE) { return (CKR_FUNCTION_FAILED); } if (template_attribute_find(tmpl, CKA_COEFFICIENT, &coeff) == FALSE) { return (CKR_FUNCTION_FAILED); } rc = ber_encode_RSAPrivateKey(length_only, data, data_len, modulus, publ_exp, priv_exp, prime1, prime2, exponent1, exponent2, coeff); return (rc); } CK_RV rsa_priv_unwrap(TEMPLATE *tmpl, CK_BYTE *data, CK_ULONG total_length) { CK_ATTRIBUTE *modulus = NULL; CK_ATTRIBUTE *publ_exp = NULL; CK_ATTRIBUTE *priv_exp = NULL; CK_ATTRIBUTE *prime1 = NULL; CK_ATTRIBUTE *prime2 = NULL; CK_ATTRIBUTE *exponent1 = NULL; CK_ATTRIBUTE *exponent2 = NULL; CK_ATTRIBUTE *coeff = NULL; CK_RV rc; rc = ber_decode_RSAPrivateKey(data, total_length, &modulus, &publ_exp, &priv_exp, &prime1, &prime2, &exponent1, &exponent2, &coeff); if (rc != CKR_OK) { return (rc); } (void) remove_leading_zeros(modulus); (void) remove_leading_zeros(publ_exp); (void) remove_leading_zeros(priv_exp); (void) remove_leading_zeros(prime1); (void) remove_leading_zeros(prime2); (void) remove_leading_zeros(exponent1); (void) remove_leading_zeros(exponent2); (void) remove_leading_zeros(coeff); (void) template_update_attribute(tmpl, modulus); (void) template_update_attribute(tmpl, publ_exp); (void) template_update_attribute(tmpl, priv_exp); (void) template_update_attribute(tmpl, prime1); (void) template_update_attribute(tmpl, prime2); (void) template_update_attribute(tmpl, exponent1); (void) template_update_attribute(tmpl, exponent2); (void) template_update_attribute(tmpl, coeff); return (CKR_OK); } CK_RV generic_secret_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL found; found = template_attribute_find(tmpl, CKA_VALUE, &attr); if (! found) { if (mode == MODE_CREATE) { return (CKR_TEMPLATE_INCOMPLETE); } } found = template_attribute_find(tmpl, CKA_VALUE_LEN, &attr); if (! found) { return (CKR_OK); } else { if (mode == MODE_CREATE) { return (CKR_ATTRIBUTE_READ_ONLY); } } return (secret_key_check_required_attributes(tmpl, mode)); } CK_RV generic_secret_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode) { CK_ATTRIBUTE *value_attr = NULL; CK_ATTRIBUTE *value_len_attr = NULL; CK_ATTRIBUTE *type_attr = NULL; CK_ULONG len = 0L; if (mode) value_attr = NULL; (void) secret_key_set_default_attributes(tmpl, mode); type_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + sizeof (CK_KEY_TYPE)); value_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE)); value_len_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + sizeof (CK_ULONG)); if (! type_attr || ! value_attr || ! value_len_attr) { if (type_attr) free(type_attr); if (value_attr) free(value_attr); if (value_len_attr) free(value_len_attr); return (CKR_HOST_MEMORY); } value_attr->type = CKA_VALUE; value_attr->ulValueLen = 0; value_attr->pValue = NULL; value_len_attr->type = CKA_VALUE_LEN; value_len_attr->ulValueLen = sizeof (CK_ULONG); value_len_attr->pValue = (CK_BYTE *)value_len_attr + sizeof (CK_ATTRIBUTE); *(CK_ULONG *)value_len_attr->pValue = len; type_attr->type = CKA_KEY_TYPE; type_attr->ulValueLen = sizeof (CK_KEY_TYPE); type_attr->pValue = (CK_BYTE *)type_attr + sizeof (CK_ATTRIBUTE); *(CK_KEY_TYPE *)type_attr->pValue = CKK_GENERIC_SECRET; (void) template_update_attribute(tmpl, type_attr); (void) template_update_attribute(tmpl, value_attr); (void) template_update_attribute(tmpl, value_len_attr); return (CKR_OK); } CK_RV generic_secret_validate_attribute(TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode) { switch (attr->type) { case CKA_VALUE: if (mode == MODE_CREATE) return (CKR_OK); else return (CKR_ATTRIBUTE_READ_ONLY); case CKA_VALUE_LEN: if (mode == MODE_KEYGEN || mode == MODE_DERIVE) return (CKR_OK); else { if (mode == MODE_UNWRAP) { return (CKR_OK); } return (CKR_ATTRIBUTE_READ_ONLY); } default: return (secret_key_validate_attribute(tmpl, attr, mode)); } } CK_BBOOL generic_secret_check_exportability(CK_ATTRIBUTE_TYPE type) { switch (type) { case CKA_VALUE: return (FALSE); } return (TRUE); } CK_RV generic_secret_wrap_get_data(TEMPLATE * tmpl, CK_BBOOL length_only, CK_BYTE ** data, CK_ULONG * data_len) { CK_ATTRIBUTE * attr = NULL; CK_BYTE * ptr = NULL; CK_RV rc; if (! tmpl || ! data_len) { return (CKR_FUNCTION_FAILED); } rc = template_attribute_find(tmpl, CKA_VALUE, &attr); if (rc == FALSE) { return (CKR_KEY_NOT_WRAPPABLE); } *data_len = attr->ulValueLen; if (length_only == FALSE) { ptr = (CK_BYTE *)malloc(attr->ulValueLen); if (! ptr) { return (CKR_HOST_MEMORY); } (void) memcpy(ptr, attr->pValue, attr->ulValueLen); *data = ptr; } return (CKR_OK); } CK_RV generic_secret_unwrap(TEMPLATE *tmpl, CK_BYTE *data, CK_ULONG data_len, CK_BBOOL fromend) { CK_ATTRIBUTE * attr = NULL; CK_ATTRIBUTE * value_attr = NULL; CK_ATTRIBUTE * value_len_attr = NULL; CK_BYTE * ptr = NULL; CK_ULONG rc, len = 0; if (fromend == TRUE) ptr = data + data_len; else ptr = data; rc = template_attribute_find(tmpl, CKA_VALUE_LEN, &attr); if (rc) { len = *(CK_ULONG *)attr->pValue; if (len > data_len) { rc = CKR_ATTRIBUTE_VALUE_INVALID; goto error; } if (len != 0) data_len = len; } if (fromend == TRUE) ptr -= data_len; rc = build_attribute(CKA_VALUE, ptr, data_len, &value_attr); if (rc != CKR_OK) { goto error; } if (data_len != len) { rc = build_attribute(CKA_VALUE_LEN, (CK_BYTE *)&data_len, sizeof (CK_ULONG), &value_len_attr); if (rc != CKR_OK) goto error; } (void) template_update_attribute(tmpl, value_attr); if (data_len != len) (void) template_update_attribute(tmpl, value_len_attr); return (CKR_OK); error: if (value_attr) free(value_attr); if (value_len_attr) free(value_len_attr); return (rc); } /* * The Initial Developer of the Original Code is International * Business Machines Corporation. Portions created by IBM * Corporation are Copyright (C) 2005 International Business * Machines Corporation. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the Common Public License as published by * IBM Corporation; either version 1 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * Common Public License for more details. * * You should have received a copy of the Common Public License * along with this program; if not, a copy can be viewed at * http://www.opensource.org/licenses/cpl1.0.php. */ /* (C) COPYRIGHT International Business Machines Corp. 2001, 2002, 2005 */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include "tpmtok_int.h" static CK_BBOOL true = TRUE, false = FALSE; static CK_RV key_mgr_get_private_key_type( CK_BYTE *keydata, CK_ULONG keylen, CK_KEY_TYPE *keytype) { CK_BYTE *alg = NULL; CK_BYTE *priv_key = NULL; CK_ULONG alg_len; CK_RV rc; rc = ber_decode_PrivateKeyInfo(keydata, keylen, &alg, &alg_len, &priv_key); if (rc != CKR_OK) { return (rc); } if (alg_len >= ber_rsaEncryptionLen) { if (memcmp(alg, ber_rsaEncryption, ber_rsaEncryptionLen) == 0) { *keytype = CKK_RSA; return (CKR_OK); } } return (CKR_TEMPLATE_INCOMPLETE); } CK_RV key_mgr_generate_key_pair(SESSION * sess, CK_MECHANISM * mech, CK_ATTRIBUTE * publ_tmpl, CK_ULONG publ_count, CK_ATTRIBUTE * priv_tmpl, CK_ULONG priv_count, CK_OBJECT_HANDLE * publ_key_handle, CK_OBJECT_HANDLE * priv_key_handle) { OBJECT * publ_key_obj = NULL; OBJECT * priv_key_obj = NULL; CK_ATTRIBUTE * attr = NULL; CK_ATTRIBUTE * new_attr = NULL; CK_ULONG i, keyclass, subclass = 0; CK_BBOOL flag; CK_RV rc; if (! sess || ! mech || ! publ_key_handle || ! priv_key_handle) { return (CKR_FUNCTION_FAILED); } if (! publ_tmpl && (publ_count != 0)) { return (CKR_FUNCTION_FAILED); } if (! priv_tmpl && (priv_count != 0)) { return (CKR_FUNCTION_FAILED); } for (i = 0; i < publ_count; i++) { if (publ_tmpl[i].type == CKA_CLASS) { keyclass = *(CK_OBJECT_CLASS *)publ_tmpl[i].pValue; if (keyclass != CKO_PUBLIC_KEY) { return (CKR_TEMPLATE_INCONSISTENT); } } if (publ_tmpl[i].type == CKA_KEY_TYPE) subclass = *(CK_ULONG *)publ_tmpl[i].pValue; } for (i = 0; i < priv_count; i++) { if (priv_tmpl[i].type == CKA_CLASS) { keyclass = *(CK_OBJECT_CLASS *)priv_tmpl[i].pValue; if (keyclass != CKO_PRIVATE_KEY) { return (CKR_TEMPLATE_INCONSISTENT); } } if (priv_tmpl[i].type == CKA_KEY_TYPE) { CK_ULONG temp = *(CK_ULONG *)priv_tmpl[i].pValue; if (temp != subclass) { return (CKR_TEMPLATE_INCONSISTENT); } } } switch (mech->mechanism) { case CKM_RSA_PKCS_KEY_PAIR_GEN: if (subclass != 0 && subclass != CKK_RSA) { return (CKR_TEMPLATE_INCONSISTENT); } subclass = CKK_RSA; break; default: return (CKR_MECHANISM_INVALID); } rc = object_mgr_create_skel(sess, publ_tmpl, publ_count, MODE_KEYGEN, CKO_PUBLIC_KEY, subclass, &publ_key_obj); if (rc != CKR_OK) { goto error; } rc = object_mgr_create_skel(sess, priv_tmpl, priv_count, MODE_KEYGEN, CKO_PRIVATE_KEY, subclass, &priv_key_obj); if (rc != CKR_OK) { goto error; } switch (mech->mechanism) { case CKM_RSA_PKCS_KEY_PAIR_GEN: rc = ckm_rsa_key_pair_gen( sess->hContext, publ_key_obj->template, priv_key_obj->template); break; default: rc = CKR_MECHANISM_INVALID; break; } if (rc != CKR_OK) { goto error; } /* * we can now set CKA_ALWAYS_SENSITIVE and CKA_NEVER_EXTRACTABLE * to their appropriate values. this only applies to CKO_SECRET_KEY * and CKO_PRIVATE_KEY objects */ flag = template_attribute_find(priv_key_obj->template, CKA_SENSITIVE, &attr); if (flag == TRUE) { flag = *(CK_BBOOL *)attr->pValue; rc = build_attribute(CKA_ALWAYS_SENSITIVE, &flag, sizeof (CK_BBOOL), &new_attr); if (rc != CKR_OK) { goto error; } (void) template_update_attribute(priv_key_obj->template, new_attr); } else { rc = CKR_FUNCTION_FAILED; goto error; } flag = template_attribute_find(priv_key_obj->template, CKA_EXTRACTABLE, &attr); if (flag == TRUE) { flag = *(CK_BBOOL *)attr->pValue; rc = build_attribute(CKA_NEVER_EXTRACTABLE, &true, sizeof (CK_BBOOL), &new_attr); if (rc != CKR_OK) { goto error; } if (flag == TRUE) *(CK_BBOOL *)new_attr->pValue = false; (void) template_update_attribute(priv_key_obj->template, new_attr); } else { rc = CKR_FUNCTION_FAILED; goto error; } rc = object_mgr_create_final(sess, publ_key_obj, publ_key_handle); if (rc != CKR_OK) { goto error; } rc = object_mgr_create_final(sess, priv_key_obj, priv_key_handle); if (rc != CKR_OK) { (void) object_mgr_destroy_object(sess, *publ_key_handle); publ_key_obj = NULL; goto error; } return (rc); error: if (publ_key_obj) (void) object_free(publ_key_obj); if (priv_key_obj) (void) object_free(priv_key_obj); *publ_key_handle = 0; *priv_key_handle = 0; return (rc); } CK_RV key_mgr_wrap_key(SESSION * sess, CK_BBOOL length_only, CK_MECHANISM * mech, CK_OBJECT_HANDLE h_wrapping_key, CK_OBJECT_HANDLE h_key, CK_BYTE * wrapped_key, CK_ULONG * wrapped_key_len) { ENCR_DECR_CONTEXT * ctx = NULL; OBJECT * key1_obj = NULL; OBJECT * key2_obj = NULL; CK_ATTRIBUTE * attr = NULL; CK_BYTE * data = NULL; CK_ULONG data_len; CK_OBJECT_CLASS class; CK_KEY_TYPE keytype; CK_BBOOL flag; CK_RV rc; if (! sess || ! wrapped_key_len) { return (CKR_FUNCTION_FAILED); } rc = object_mgr_find_in_map1(sess->hContext, h_wrapping_key, &key1_obj); if (rc != CKR_OK) { return (CKR_WRAPPING_KEY_HANDLE_INVALID); } rc = object_mgr_find_in_map1(sess->hContext, h_key, &key2_obj); if (rc != CKR_OK) { return (CKR_KEY_HANDLE_INVALID); } rc = template_attribute_find(key2_obj->template, CKA_EXTRACTABLE, &attr); if (rc == FALSE) { return (CKR_KEY_NOT_WRAPPABLE); } else { flag = *(CK_BBOOL *)attr->pValue; if (flag == FALSE) { return (CKR_KEY_NOT_WRAPPABLE); } } rc = template_attribute_find(key2_obj->template, CKA_CLASS, &attr); if (rc == FALSE) { return (CKR_KEY_NOT_WRAPPABLE); } else class = *(CK_OBJECT_CLASS *)attr->pValue; switch (mech->mechanism) { case CKM_RSA_PKCS: if (class != CKO_SECRET_KEY) { return (CKR_KEY_NOT_WRAPPABLE); } break; default: return (CKR_KEY_NOT_WRAPPABLE); } rc = template_attribute_find(key2_obj->template, CKA_KEY_TYPE, &attr); if (rc == FALSE) return (CKR_KEY_NOT_WRAPPABLE); else keytype = *(CK_KEY_TYPE *)attr->pValue; switch (keytype) { case CKK_RSA: rc = rsa_priv_wrap_get_data(key2_obj->template, length_only, &data, &data_len); if (rc != CKR_OK) { return (rc); } break; case CKK_GENERIC_SECRET: rc = generic_secret_wrap_get_data(key2_obj->template, length_only, &data, &data_len); if (rc != CKR_OK) { return (rc); } break; default: return (CKR_KEY_NOT_WRAPPABLE); } switch (mech->mechanism) { case CKM_RSA_PKCS: break; default: return (CKR_KEY_NOT_WRAPPABLE); } ctx = (ENCR_DECR_CONTEXT *)malloc(sizeof (ENCR_DECR_CONTEXT)); if (! ctx) { return (CKR_HOST_MEMORY); } (void) memset(ctx, 0x0, sizeof (ENCR_DECR_CONTEXT)); rc = encr_mgr_init(sess, ctx, OP_WRAP, mech, h_wrapping_key); if (rc != CKR_OK) { return (rc); } rc = encr_mgr_encrypt(sess, length_only, ctx, data, data_len, wrapped_key, wrapped_key_len); if (data != NULL) { free(data); } (void) encr_mgr_cleanup(ctx); free(ctx); return (rc); } CK_RV key_mgr_unwrap_key(SESSION * sess, CK_MECHANISM * mech, CK_ATTRIBUTE * attributes, CK_ULONG attrib_count, CK_BYTE * wrapped_key, CK_ULONG wrapped_key_len, CK_OBJECT_HANDLE h_unwrapping_key, CK_OBJECT_HANDLE * h_unwrapped_key) { ENCR_DECR_CONTEXT * ctx = NULL; OBJECT * key_obj = NULL; CK_BYTE * data = NULL; CK_ULONG data_len; CK_ULONG keyclass, keytype; CK_ULONG i; CK_BBOOL found_class, found_type, fromend; CK_RV rc; if (! sess || ! wrapped_key || ! h_unwrapped_key) { return (CKR_FUNCTION_FAILED); } rc = object_mgr_find_in_map1(sess->hContext, h_unwrapping_key, &key_obj); if (rc != CKR_OK) { return (CKR_WRAPPING_KEY_HANDLE_INVALID); } found_class = FALSE; found_type = FALSE; switch (mech->mechanism) { case CKM_RSA_PKCS: keyclass = CKO_SECRET_KEY; found_class = TRUE; break; } for (i = 0; i < attrib_count; i++) { switch (attributes[i].type) { case CKA_CLASS: keyclass = *(CK_OBJECT_CLASS *)attributes[i].pValue; found_class = TRUE; break; case CKA_KEY_TYPE: keytype = *(CK_KEY_TYPE *)attributes[i].pValue; found_type = TRUE; break; } } if (found_class == FALSE || (found_type == FALSE && keyclass != CKO_PRIVATE_KEY)) { return (CKR_TEMPLATE_INCOMPLETE); } switch (mech->mechanism) { case CKM_RSA_PKCS: if (keyclass != CKO_SECRET_KEY) { return (CKR_TEMPLATE_INCONSISTENT); } break; default: return (CKR_MECHANISM_INVALID); } ctx = (ENCR_DECR_CONTEXT *)malloc(sizeof (ENCR_DECR_CONTEXT)); if (! ctx) { return (CKR_HOST_MEMORY); } (void) memset(ctx, 0x0, sizeof (ENCR_DECR_CONTEXT)); rc = decr_mgr_init(sess, ctx, OP_UNWRAP, mech, h_unwrapping_key); if (rc != CKR_OK) return (rc); rc = decr_mgr_decrypt(sess, TRUE, ctx, wrapped_key, wrapped_key_len, data, &data_len); if (rc != CKR_OK) { goto error; } data = (CK_BYTE *)malloc(data_len); if (! data) { rc = CKR_HOST_MEMORY; goto error; } rc = decr_mgr_decrypt(sess, FALSE, ctx, wrapped_key, wrapped_key_len, data, &data_len); (void) decr_mgr_cleanup(ctx); free(ctx); if (rc != CKR_OK) { goto error; } /* * if we use X.509, the data will be padded from the front with zeros. * PKCS #11 specifies that for this mechanism, CK_VALUE is to be read * from the end of the data. * * Note: the PKCS #11 reference implementation gets this wrong. */ if (mech->mechanism == CKM_RSA_X_509) fromend = TRUE; else fromend = FALSE; if (keyclass == CKO_PRIVATE_KEY) { rc = key_mgr_get_private_key_type(data, data_len, &keytype); if (rc != CKR_OK) { goto error; } } rc = object_mgr_create_skel(sess, attributes, attrib_count, MODE_UNWRAP, keyclass, keytype, &key_obj); if (rc != CKR_OK) { goto error; } switch (keyclass) { case CKO_SECRET_KEY: rc = secret_key_unwrap(key_obj->template, keytype, data, data_len, fromend); break; case CKO_PRIVATE_KEY: rc = priv_key_unwrap(key_obj->template, keytype, data, data_len); break; default: rc = CKR_WRAPPED_KEY_INVALID; break; } if (rc != CKR_OK) { goto error; } rc = object_mgr_create_final(sess, key_obj, h_unwrapped_key); if (rc != CKR_OK) { goto error; } if (data) free(data); return (rc); error: if (key_obj) (void) object_free(key_obj); if (data) free(data); return (rc); } /* * 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 */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include "tpmtok_int.h" #include #include #include #define ALTERNATE_KEYSTORE_PATH "PKCS11_TPM_DIR" #define PWD_BUFFER_SIZE 1024 static char keystore_path[MAXPATHLEN]; static boolean_t keystore_path_initialized = 0; extern TSS_HKEY hPrivateLeafKey; static CK_RV restore_private_token_object(TSS_HCONTEXT, CK_BYTE *, CK_ULONG, OBJECT *); static struct flock fl = { 0, 0, 0, 0, 0, 0, {0, 0, 0, 0} }; static int lockfile(int fd, int op) { fl.l_type = op; return (fcntl(fd, F_SETLKW, &fl)); } static char * get_user_default_path(char *home_path) { struct passwd pwd, *user_info; char pwdbuf[PWD_BUFFER_SIZE]; if (getpwuid_r(getuid(), &pwd, pwdbuf, PWD_BUFFER_SIZE, &user_info) != 0) return (NULL); (void) snprintf(home_path, MAXPATHLEN, "/var/tpm/pkcs11/%s", user_info ? user_info->pw_name : ""); return (home_path); } char * get_tpm_keystore_path() { char *env_val; char home_path[MAXPATHLEN]; if (!keystore_path_initialized) { env_val = getenv(ALTERNATE_KEYSTORE_PATH); bzero(keystore_path, sizeof (keystore_path)); /* * If it isn't set or is set to the empty string use the * default location. We need to check for the empty string * because some users "unset" environment variables by giving * them no value, this isn't the same thing as removing it * from the environment. * * We don't want that to attempt to open the token area. */ if ((env_val == NULL) || (strcmp(env_val, "") == 0)) { /* alternate path not specified, use default dir */ char *p = get_user_default_path(home_path); if (p == NULL) return (NULL); (void) snprintf(keystore_path, MAXPATHLEN, "%s", p); } else { (void) snprintf(keystore_path, MAXPATHLEN, "%s", env_val); } keystore_path_initialized = 1; } return (keystore_path); } static CK_RV create_keystore_dir() { char *ksdir = get_tpm_keystore_path(); char objdir[MAXPATHLEN]; CK_RV rv = 0; if (ksdir == NULL) return (CKR_FUNCTION_FAILED); if (mkdir(ksdir, S_IRUSR|S_IWUSR|S_IXUSR) < 0) { if (errno == EEXIST) { rv = 0; } else { return (CKR_FUNCTION_FAILED); } } if (rv == 0) { (void) snprintf(objdir, sizeof (objdir), "%s/%s", ksdir, TOKEN_OBJ_DIR); if (mkdir(objdir, S_IRUSR|S_IWUSR|S_IXUSR) < 0) { if (errno == EEXIST) { rv = 0; } else { return (CKR_FUNCTION_FAILED); } } } return (CKR_OK); } static void set_perm(int file) { /* * In the TPM token, with per user data stores, we don't share the token * object amongst a group. In fact, we want to restrict access to * a single user. */ (void) fchmod(file, S_IRUSR|S_IWUSR); } #define READ_TOKEN_INFO_STR(fp, rec, reclen) rc = fread(rec, reclen, 1, fp); \ if (rc != 1) { rc = CKR_FUNCTION_FAILED; goto out_unlock; } #define READ_TOKEN_INFO_UINT32(fp, rec) rc = fread(&fieldval, \ sizeof (UINT32), 1, fp); \ if (rc != 1) { rc = CKR_FUNCTION_FAILED; goto out_unlock; } \ rec = (CK_ULONG)fieldval; CK_RV load_token_data(TSS_HCONTEXT hContext, TOKEN_DATA *td) { FILE *fp; CK_BYTE fname[MAXPATHLEN]; CK_RV rc; UINT32 fieldval; char *p = get_tpm_keystore_path(); if (p == NULL) return (CKR_FUNCTION_FAILED); (void) snprintf((char *)fname, sizeof (fname), "%s/%s", p, TOKEN_DATA_FILE); rc = XProcLock(xproclock); if (rc != CKR_OK) return (rc); fp = fopen((char *)fname, "r"); if (!fp) { /* Better error checking added */ if (errno == ENOENT) { (void) XProcUnLock(xproclock); rc = create_keystore_dir(); if (rc != 0) goto out_nolock; rc = init_token_data(hContext, td); if (rc != CKR_OK) { goto out_nolock; } rc = XProcLock(xproclock); if (rc != CKR_OK) { goto out_nolock; } fp = fopen((char *)fname, "r"); if (!fp) { LogError("failed opening %s for read: %s", fname, (char *)strerror(errno)); rc = CKR_FUNCTION_FAILED; goto out_unlock; } } else { /* Could not open file for some unknown reason */ rc = CKR_FUNCTION_FAILED; goto out_unlock; } } if (lockfile(fileno(fp), F_RDLCK)) { (void) fclose(fp); rc = CKR_FUNCTION_FAILED; goto out_unlock; } set_perm(fileno(fp)); /* Read fields individually because of 64-bit size diffs */ READ_TOKEN_INFO_STR(fp, td->token_info.label, sizeof (td->token_info.label)); READ_TOKEN_INFO_STR(fp, td->token_info.manufacturerID, sizeof (td->token_info.manufacturerID)); READ_TOKEN_INFO_STR(fp, td->token_info.model, sizeof (td->token_info.model)); READ_TOKEN_INFO_STR(fp, td->token_info.serialNumber, sizeof (td->token_info.serialNumber)); READ_TOKEN_INFO_UINT32(fp, td->token_info.flags); READ_TOKEN_INFO_UINT32(fp, td->token_info.ulMaxSessionCount); READ_TOKEN_INFO_UINT32(fp, td->token_info.ulSessionCount); READ_TOKEN_INFO_UINT32(fp, td->token_info.ulRwSessionCount); READ_TOKEN_INFO_UINT32(fp, td->token_info.ulMaxPinLen); READ_TOKEN_INFO_UINT32(fp, td->token_info.ulMinPinLen); READ_TOKEN_INFO_UINT32(fp, td->token_info.ulTotalPublicMemory); READ_TOKEN_INFO_UINT32(fp, td->token_info.ulFreePublicMemory); READ_TOKEN_INFO_UINT32(fp, td->token_info.ulTotalPrivateMemory); READ_TOKEN_INFO_UINT32(fp, td->token_info.ulFreePrivateMemory); READ_TOKEN_INFO_STR(fp, &td->token_info.hardwareVersion, sizeof (td->token_info.hardwareVersion)); READ_TOKEN_INFO_STR(fp, &td->token_info.firmwareVersion, sizeof (td->token_info.firmwareVersion)); READ_TOKEN_INFO_STR(fp, td->token_info.utcTime, sizeof (td->token_info.utcTime)); READ_TOKEN_INFO_STR(fp, td->user_pin_sha, sizeof (td->user_pin_sha)); READ_TOKEN_INFO_STR(fp, td->so_pin_sha, sizeof (td->so_pin_sha)); READ_TOKEN_INFO_STR(fp, td->next_token_object_name, sizeof (td->next_token_object_name)); READ_TOKEN_INFO_STR(fp, &td->tweak_vector, sizeof (td->tweak_vector)); (void) lockfile(fileno(fp), F_UNLCK); (void) fclose(fp); if (rc == 0) rc = CKR_FUNCTION_FAILED; else rc = CKR_OK; out_unlock: (void) XProcUnLock(xproclock); out_nolock: return (rc); } #define WRITE_TOKEN_INFO_STR(fp, rec, reclen) rc = fwrite(rec, reclen, 1, fp); \ if (rc != 1) { rc = CKR_FUNCTION_FAILED; goto done; } #define WRITE_TOKEN_INFO_UINT32(fp, rec) fieldval = (UINT32)rec; \ rc = fwrite(&fieldval, sizeof (UINT32), 1, fp); \ if (rc != 1) { rc = CKR_FUNCTION_FAILED; goto done; } CK_RV save_token_data(TOKEN_DATA *td) { FILE *fp; CK_RV rc; CK_BYTE fname[MAXPATHLEN]; char *p = get_tpm_keystore_path(); UINT32 fieldval; if (p == NULL) return (CKR_FUNCTION_FAILED); (void) snprintf((char *)fname, sizeof (fname), "%s/%s", p, TOKEN_DATA_FILE); rc = XProcLock(xproclock); if (rc != CKR_OK) goto out_nolock; fp = fopen((char *)fname, "w"); if (!fp) { rc = CKR_FUNCTION_FAILED; goto done; } if (lockfile(fileno(fp), F_WRLCK)) { rc = CKR_FUNCTION_FAILED; (void) fclose(fp); goto done; } set_perm(fileno(fp)); /* Write token fields individually to maintain sizes on 64 and 32 bit */ WRITE_TOKEN_INFO_STR(fp, td->token_info.label, sizeof (td->token_info.label)); WRITE_TOKEN_INFO_STR(fp, td->token_info.manufacturerID, sizeof (td->token_info.manufacturerID)); WRITE_TOKEN_INFO_STR(fp, td->token_info.model, sizeof (td->token_info.model)); WRITE_TOKEN_INFO_STR(fp, td->token_info.serialNumber, sizeof (td->token_info.serialNumber)); WRITE_TOKEN_INFO_UINT32(fp, td->token_info.flags); WRITE_TOKEN_INFO_UINT32(fp, td->token_info.ulMaxSessionCount); WRITE_TOKEN_INFO_UINT32(fp, td->token_info.ulSessionCount); WRITE_TOKEN_INFO_UINT32(fp, td->token_info.ulRwSessionCount); WRITE_TOKEN_INFO_UINT32(fp, td->token_info.ulMaxPinLen); WRITE_TOKEN_INFO_UINT32(fp, td->token_info.ulMinPinLen); WRITE_TOKEN_INFO_UINT32(fp, td->token_info.ulTotalPublicMemory); WRITE_TOKEN_INFO_UINT32(fp, td->token_info.ulFreePublicMemory); WRITE_TOKEN_INFO_UINT32(fp, td->token_info.ulTotalPrivateMemory); WRITE_TOKEN_INFO_UINT32(fp, td->token_info.ulFreePrivateMemory); WRITE_TOKEN_INFO_STR(fp, &td->token_info.hardwareVersion, sizeof (td->token_info.hardwareVersion)); WRITE_TOKEN_INFO_STR(fp, &td->token_info.firmwareVersion, sizeof (td->token_info.firmwareVersion)); WRITE_TOKEN_INFO_STR(fp, td->token_info.utcTime, sizeof (td->token_info.utcTime)); WRITE_TOKEN_INFO_STR(fp, td->user_pin_sha, sizeof (td->user_pin_sha)); WRITE_TOKEN_INFO_STR(fp, td->so_pin_sha, sizeof (td->so_pin_sha)); WRITE_TOKEN_INFO_STR(fp, td->next_token_object_name, sizeof (td->next_token_object_name)); WRITE_TOKEN_INFO_STR(fp, &td->tweak_vector, sizeof (td->tweak_vector)); (void) lockfile(fileno(fp), F_UNLCK); (void) fclose(fp); rc = CKR_OK; done: (void) XProcUnLock(xproclock); out_nolock: return (rc); } CK_RV save_token_object(TSS_HCONTEXT hContext, OBJECT *obj) { FILE *fp = NULL; CK_BYTE line[100]; CK_RV rc; CK_BYTE fname[MAXPATHLEN]; char *p = get_tpm_keystore_path(); if (p == NULL) return (CKR_FUNCTION_FAILED); if (object_is_private(obj) == TRUE) rc = save_private_token_object(hContext, obj); else rc = save_public_token_object(obj); if (rc != CKR_OK) return (rc); (void) snprintf((char *)fname, sizeof (fname), "%s/%s/%s", p, TOKEN_OBJ_DIR, TOKEN_OBJ_INDEX_FILE); fp = fopen((char *)fname, "r"); if (fp) { if (lockfile(fileno(fp), F_RDLCK)) { (void) fclose(fp); return (CKR_FUNCTION_FAILED); } set_perm(fileno(fp)); while (!feof(fp)) { (void) fgets((char *)line, 50, fp); if (!feof(fp)) { line[strlen((char *)line) - 1] = 0; if (strcmp((char *)line, (char *)(obj->name)) == 0) { (void) lockfile(fileno(fp), F_UNLCK); (void) fclose(fp); return (CKR_OK); } } } (void) lockfile(fileno(fp), F_UNLCK); (void) fclose(fp); } fp = fopen((char *)fname, "a"); if (!fp) return (CKR_FUNCTION_FAILED); if (lockfile(fileno(fp), F_WRLCK)) { (void) fclose(fp); return (CKR_FUNCTION_FAILED); } set_perm(fileno(fp)); (void) fprintf(fp, "%s\n", obj->name); (void) lockfile(fileno(fp), F_UNLCK); (void) fclose(fp); return (CKR_OK); } CK_RV save_public_token_object(OBJECT *obj) { FILE *fp = NULL; CK_BYTE *cleartxt = NULL; CK_BYTE fname[MAXPATHLEN]; UINT32 cleartxt_len; CK_BBOOL flag = FALSE; CK_RV rc; UINT32 total_len; char *p = get_tpm_keystore_path(); if (p == NULL) return (CKR_FUNCTION_FAILED); (void) snprintf((char *)fname, sizeof (fname), "%s/%s/%s", p, TOKEN_OBJ_DIR, obj->name); rc = object_flatten(obj, &cleartxt, &cleartxt_len); if (rc != CKR_OK) goto error; fp = fopen((char *)fname, "w"); if (!fp) { LogError("Error opening %s - %s", fname, (char *)strerror(errno)); rc = CKR_FUNCTION_FAILED; goto error; } if (lockfile(fileno(fp), F_WRLCK)) { (void) fclose(fp); return (CKR_FUNCTION_FAILED); } set_perm(fileno(fp)); total_len = cleartxt_len + sizeof (UINT32) + sizeof (CK_BBOOL); (void) fwrite(&total_len, sizeof (total_len), 1, fp); (void) fwrite(&flag, sizeof (flag), 1, fp); (void) fwrite(cleartxt, cleartxt_len, 1, fp); (void) lockfile(fileno(fp), F_UNLCK); (void) fclose(fp); free(cleartxt); return (CKR_OK); error: if (fp) (void) fclose(fp); if (cleartxt) free(cleartxt); return (rc); } CK_RV save_private_token_object(TSS_HCONTEXT hContext, OBJECT *obj) { FILE *fp = NULL; CK_BYTE *obj_data = NULL; CK_BYTE *cleartxt = NULL; CK_BYTE *ciphertxt = NULL; CK_BYTE *ptr = NULL; CK_BYTE fname[100]; CK_BYTE hash_sha[SHA1_DIGEST_LENGTH]; CK_BBOOL flag; CK_RV rc; CK_ULONG ciphertxt_len; UINT32 cleartxt_len; UINT32 padded_len; UINT32 obj_data_len_32; UINT32 total_len; UINT32 chunksize, blocks; char *p = get_tpm_keystore_path(); if (p == NULL) return (CKR_FUNCTION_FAILED); rc = object_flatten(obj, &obj_data, &obj_data_len_32); if (rc != CKR_OK) { goto error; } /* * format for the object file: * private flag * ---- begin encrypted part <--+ * length of object data (4 bytes) | * object data +---- sensitive part * SHA of (object data) | * ---- end encrypted part <--+ */ if ((rc = compute_sha(obj_data, obj_data_len_32, hash_sha)) != CKR_OK) goto error; /* * RSA OAEP crypto uses chunks smaller than the max to make room * for the hashes. * chunksize = RSA_Modulus_Size - (2 * SHA1_DIGEST_SIZE + 2) - (4 - 1) * == 209 */ chunksize = RSA_BLOCK_SIZE - (2 * SHA1_DIGEST_LENGTH + 2) - 5; cleartxt_len = sizeof (UINT32) + obj_data_len_32 + SHA1_DIGEST_LENGTH; blocks = cleartxt_len / chunksize + ((cleartxt_len % chunksize) > 0); padded_len = RSA_BLOCK_SIZE * blocks; cleartxt = (CK_BYTE *)malloc(padded_len); ciphertxt = (CK_BYTE *)malloc(padded_len); if (!cleartxt || !ciphertxt) { rc = CKR_HOST_MEMORY; goto error; } ciphertxt_len = padded_len; ptr = cleartxt; (void) memcpy(ptr, &obj_data_len_32, sizeof (UINT32)); ptr += sizeof (UINT32); (void) memcpy(ptr, obj_data, obj_data_len_32); ptr += obj_data_len_32; (void) memcpy(ptr, hash_sha, SHA1_DIGEST_LENGTH); (void) add_pkcs_padding(cleartxt + cleartxt_len, RSA_BLOCK_SIZE, cleartxt_len, padded_len); /* the encrypt function will compute the padded length */ rc = tpm_encrypt_data(hContext, hPrivateLeafKey, cleartxt, cleartxt_len, ciphertxt, &ciphertxt_len); if (rc != CKR_OK) { goto error; } (void) snprintf((char *)fname, sizeof (fname), "%s/%s/%s", p, TOKEN_OBJ_DIR, obj->name); fp = fopen((char *)fname, "w"); if (!fp) { rc = CKR_FUNCTION_FAILED; goto error; } if (lockfile(fileno(fp), F_WRLCK)) { rc = CKR_FUNCTION_FAILED; goto error; } set_perm(fileno(fp)); total_len = sizeof (UINT32) + sizeof (CK_BBOOL) + (UINT32)ciphertxt_len; flag = TRUE; (void) fwrite(&total_len, sizeof (UINT32), 1, fp); (void) fwrite(&flag, sizeof (CK_BBOOL), 1, fp); (void) fwrite(ciphertxt, ciphertxt_len, 1, fp); (void) lockfile(fileno(fp), F_UNLCK); (void) fclose(fp); free(obj_data); free(cleartxt); free(ciphertxt); return (CKR_OK); error: if (fp) (void) fclose(fp); if (obj_data) free(obj_data); if (cleartxt) free(cleartxt); if (ciphertxt) free(ciphertxt); return (rc); } CK_RV load_public_token_objects(void) { FILE *fp1 = NULL, *fp2 = NULL; CK_BYTE *buf = NULL; CK_BYTE tmp[MAXPATHLEN], fname[MAXPATHLEN], iname[MAXPATHLEN]; CK_BBOOL priv; UINT32 size; char *ksdir = get_tpm_keystore_path(); if (ksdir == NULL) return (CKR_FUNCTION_FAILED); (void) snprintf((char *)iname, sizeof (iname), "%s/%s/%s", ksdir, TOKEN_OBJ_DIR, TOKEN_OBJ_INDEX_FILE); fp1 = fopen((char *)iname, "r"); if (!fp1) return (CKR_OK); // no token objects if (lockfile(fileno(fp1), F_RDLCK)) { (void) fclose(fp1); return (CKR_FUNCTION_FAILED); } while (!feof(fp1)) { (void) fgets((char *)tmp, 50, fp1); if (feof(fp1)) break; tmp[strlen((char *)tmp) - 1] = 0; (void) snprintf((char *)fname, sizeof (fname), "%s/%s/", ksdir, TOKEN_OBJ_DIR); (void) strncat((char *)fname, (const char *)tmp, (size_t)sizeof (fname)); fp2 = fopen((char *)fname, "r"); if (!fp2) continue; (void) fread(&size, sizeof (UINT32), 1, fp2); (void) fread(&priv, sizeof (CK_BBOOL), 1, fp2); if (priv == TRUE) { (void) fclose(fp2); continue; } size = size - sizeof (UINT32) - sizeof (CK_BBOOL); buf = (CK_BYTE *)malloc(size); if (!buf) { (void) lockfile(fileno(fp1), F_UNLCK); (void) fclose(fp1); (void) fclose(fp2); return (CKR_HOST_MEMORY); } (void) fread(buf, size, 1, fp2); if (pthread_mutex_lock(&obj_list_mutex)) { (void) lockfile(fileno(fp1), F_UNLCK); (void) fclose(fp1); (void) fclose(fp2); free(buf); return (CKR_FUNCTION_FAILED); } (void) object_mgr_restore_obj(buf, NULL); (void) pthread_mutex_unlock(&obj_list_mutex); free(buf); (void) fclose(fp2); } (void) lockfile(fileno(fp1), F_UNLCK); (void) fclose(fp1); return (CKR_OK); } CK_RV load_private_token_objects(TSS_HCONTEXT hContext) { FILE *fp1 = NULL, *fp2 = NULL; CK_BYTE *buf = NULL; CK_BYTE tmp[MAXPATHLEN], fname[MAXPATHLEN], iname[MAXPATHLEN]; CK_BBOOL priv; UINT32 size; CK_RV rc; char *ksdir = get_tpm_keystore_path(); if (ksdir == NULL) return (CKR_FUNCTION_FAILED); (void) snprintf((char *)iname, sizeof (iname), "%s/%s/%s", ksdir, TOKEN_OBJ_DIR, TOKEN_OBJ_INDEX_FILE); fp1 = fopen((char *)iname, "r"); if (!fp1) return (CKR_OK); if (lockfile(fileno(fp1), F_RDLCK)) { rc = CKR_FUNCTION_FAILED; goto error; } while (!feof(fp1)) { (void) fgets((char *)tmp, sizeof (tmp), fp1); if (feof(fp1)) break; tmp[strlen((char *)tmp) - 1] = 0; (void) snprintf((char *)fname, sizeof (fname), "%s/%s/%s", ksdir, TOKEN_OBJ_DIR, tmp); fp2 = fopen((char *)fname, "r"); if (!fp2) continue; (void) fread(&size, sizeof (UINT32), 1, fp2); (void) fread(&priv, sizeof (CK_BBOOL), 1, fp2); if (priv == FALSE) { (void) fclose(fp2); continue; } size = size - sizeof (UINT32) - sizeof (CK_BBOOL); buf = (CK_BYTE *)malloc(size); if (!buf) { rc = CKR_HOST_MEMORY; goto error; } rc = fread((char *)buf, size, 1, fp2); if (rc != 1) { rc = CKR_FUNCTION_FAILED; goto error; } if (pthread_mutex_lock(&obj_list_mutex)) { rc = CKR_FUNCTION_FAILED; goto error; } rc = restore_private_token_object(hContext, buf, size, NULL); (void) pthread_mutex_unlock(&obj_list_mutex); if (rc != CKR_OK) goto error; free(buf); (void) fclose(fp2); } (void) lockfile(fileno(fp1), F_UNLCK); (void) fclose(fp1); return (CKR_OK); error: if (buf) free(buf); if (fp1) { (void) lockfile(fileno(fp1), F_UNLCK); (void) fclose(fp1); } if (fp2) (void) fclose(fp2); return (rc); } static CK_RV restore_private_token_object( TSS_HCONTEXT hContext, CK_BYTE *data, CK_ULONG len, OBJECT *pObj) { CK_BYTE * cleartxt = NULL; CK_BYTE * obj_data = NULL; CK_BYTE *ptr = NULL; CK_BYTE hash_sha[SHA1_DIGEST_LENGTH]; UINT32 cleartxt_len; UINT32 obj_data_len; CK_RV rc; /* * format for the object data: * (private flag has already been read at this point) * ---- begin encrypted part * length of object data (4 bytes) * object data * SHA of object data * ---- end encrypted part */ cleartxt_len = len; cleartxt = (CK_BYTE *)malloc(len); if (!cleartxt) { rc = CKR_HOST_MEMORY; goto done; } rc = tpm_decrypt_data(hContext, hPrivateLeafKey, data, len, cleartxt, &len); if (rc != CKR_OK) { goto done; } (void) strip_pkcs_padding(cleartxt, len, &cleartxt_len); if (cleartxt_len > len) { rc = CKR_FUNCTION_FAILED; goto done; } ptr = cleartxt; bcopy(ptr, &obj_data_len, sizeof (UINT32)); ptr += sizeof (UINT32); obj_data = ptr; if ((rc = compute_sha(ptr, obj_data_len, hash_sha)) != CKR_OK) goto done; ptr += obj_data_len; if (memcmp((const void *)ptr, (const void *)hash_sha, (size_t)SHA1_DIGEST_LENGTH) != 0) { rc = CKR_FUNCTION_FAILED; goto done; } (void) object_mgr_restore_obj(obj_data, pObj); rc = CKR_OK; done: if (cleartxt) free(cleartxt); return (rc); } CK_RV reload_token_object(TSS_HCONTEXT hContext, OBJECT *obj) { FILE *fp = NULL; CK_BYTE *buf = NULL; CK_BYTE fname[MAXPATHLEN]; CK_BBOOL priv; UINT32 size; CK_RV rc; char *p = get_tpm_keystore_path(); if (p == NULL) return (CKR_FUNCTION_FAILED); (void) memset((char *)fname, 0x0, sizeof (fname)); (void) snprintf((char *)fname, sizeof (fname), "%s/%s/", p, TOKEN_OBJ_DIR); (void) strncat((char *)fname, (char *)obj->name, sizeof (fname)); fp = fopen((char *)fname, "r"); if (!fp) { rc = CKR_FUNCTION_FAILED; goto done; } if (lockfile(fileno(fp), F_RDLCK)) { rc = CKR_FUNCTION_FAILED; goto done; } set_perm(fileno(fp)); (void) fread(&size, sizeof (UINT32), 1, fp); (void) fread(&priv, sizeof (CK_BBOOL), 1, fp); size = size - sizeof (UINT32) - sizeof (CK_BBOOL); buf = (CK_BYTE *)malloc(size); if (!buf) { rc = CKR_HOST_MEMORY; goto done; } (void) fread(buf, size, 1, fp); if (priv) { rc = restore_private_token_object(hContext, buf, size, obj); } else { rc = object_mgr_restore_obj(buf, obj); } done: if (fp) { (void) lockfile(fileno(fp), F_UNLCK); (void) fclose(fp); } if (buf) free(buf); return (rc); } static int islink(char *fname) { struct stat st; if (stat((const char *)fname, &st)) return (-1); else if (S_ISLNK(st.st_mode)) return (1); return (0); } CK_RV delete_token_object(OBJECT *obj) { FILE *fp1, *fp2; CK_BYTE line[100]; char objidx[MAXPATHLEN], idxtmp[MAXPATHLEN], fname[MAXPATHLEN]; char *ksdir = get_tpm_keystore_path(); if (ksdir == NULL) return (CKR_FUNCTION_FAILED); (void) snprintf(objidx, sizeof (objidx), "%s/%s/%s", ksdir, TOKEN_OBJ_DIR, TOKEN_OBJ_INDEX_FILE); (void) snprintf(idxtmp, sizeof (idxtmp), "%s/IDX.TMP", ksdir, TOKEN_OBJ_DIR); /* * If either file is a link, fail. */ if (islink(objidx) != 0) return (CKR_FUNCTION_FAILED); /* * idxtmp is a temporary file (and should not exist yet), only fail * if it is already an existing link. */ if (islink(idxtmp) == 1) return (CKR_FUNCTION_FAILED); fp1 = fopen(objidx, "r"); fp2 = fopen(idxtmp, "w"); if (!fp1 || !fp2) { if (fp1) (void) fclose(fp1); if (fp2) (void) fclose(fp2); return (CKR_FUNCTION_FAILED); } if (lockfile(fileno(fp1), F_RDLCK)) { (void) fclose(fp1); (void) fclose(fp2); return (CKR_FUNCTION_FAILED); } if (lockfile(fileno(fp2), F_WRLCK)) { (void) lockfile(fileno(fp1), F_UNLCK); (void) fclose(fp1); (void) fclose(fp2); return (CKR_FUNCTION_FAILED); } set_perm(fileno(fp2)); while (!feof(fp1)) { (void) fgets((char *)line, 50, fp1); if (!feof(fp1)) { line[ strlen((char *)line)-1 ] = 0; if (strcmp((char *)line, (char *)obj->name)) (void) fprintf(fp2, "%s\n", line); } } (void) lockfile(fileno(fp1), F_UNLCK); (void) lockfile(fileno(fp2), F_UNLCK); (void) fclose(fp1); (void) fclose(fp2); fp2 = fopen(objidx, "w"); fp1 = fopen(idxtmp, "r"); if (!fp1 || !fp2) { if (fp1) (void) fclose(fp1); if (fp2) (void) fclose(fp2); return (CKR_FUNCTION_FAILED); } if (lockfile(fileno(fp1), F_RDLCK)) { (void) fclose(fp1); (void) fclose(fp2); return (CKR_FUNCTION_FAILED); } if (lockfile(fileno(fp2), F_WRLCK)) { (void) lockfile(fileno(fp1), F_UNLCK); (void) fclose(fp1); (void) fclose(fp2); return (CKR_FUNCTION_FAILED); } set_perm(fileno(fp2)); while (!feof(fp1)) { (void) fgets((char *)line, 50, fp1); if (!feof(fp1)) (void) fprintf(fp2, "%s", (char *)line); } (void) lockfile(fileno(fp1), F_UNLCK); (void) lockfile(fileno(fp2), F_UNLCK); (void) fclose(fp1); (void) fclose(fp2); (void) snprintf(fname, sizeof (fname), "%s/%s/%s", ksdir, TOKEN_OBJ_DIR, (char *)obj->name); (void) unlink(fname); return (CKR_OK); } /* * Common Public License Version 0.5 * * THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF * THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, * REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES * RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. * * 1. DEFINITIONS * * "Contribution" means: * a) in the case of the initial Contributor, the * initial code and documentation distributed under * this Agreement, and * * b) in the case of each subsequent Contributor: * i) changes to the Program, and * ii) additions to the Program; * * where such changes and/or additions to the Program * originate from and are distributed by that * particular Contributor. A Contribution 'originates' * from a Contributor if it was added to the Program * by such Contributor itself or anyone acting on such * Contributor's behalf. Contributions do not include * additions to the Program which: (i) are separate * modules of software distributed in conjunction with * the Program under their own license agreement, and * (ii) are not derivative works of the Program. * * * "Contributor" means any person or entity that distributes * the Program. * * "Licensed Patents " mean patent claims licensable by a * Contributor which are necessarily infringed by the use or * sale of its Contribution alone or when combined with the * Program. * * "Program" means the Contributions distributed in * accordance with this Agreement. * * "Recipient" means anyone who receives the Program under * this Agreement, including all Contributors. * * 2. GRANT OF RIGHTS * * a) Subject to the terms of this Agreement, each * Contributor hereby grants Recipient a * no - exclusive, worldwide, royalt - free copyright * license to reproduce, prepare derivative works of, * publicly display, publicly perform, distribute and * sublicense the Contribution of such Contributor, if * any, and such derivative works, in source code and * object code form. * * b) Subject to the terms of this Agreement, each * Contributor hereby grants Recipient a * no - exclusive, worldwide, royalt - free patent * license under Licensed Patents to make, use, sell, * offer to sell, import and otherwise transfer the * Contribution of such Contributor, if any, in source * code and object code form. This patent license * shall apply to the combination of the Contribution * and the Program if, at the time the Contribution is * added by the Contributor, such addition of the * Contribution causes such combination to be covered * by the Licensed Patents. The patent license shall * not apply to any other combinations which include * the Contribution. No hardware per se is licensed * hereunder. * * c) Recipient understands that although each * Contributor grants the licenses to its * Contributions set forth herein, no assurances are * provided by any Contributor that the Program does * not infringe the patent or other intellectual * property rights of any other entity. Each * Contributor disclaims any liability to Recipient * for claims brought by any other entity based on * infringement of intellectual property rights or * otherwise. As a condition to exercising the rights * and licenses granted hereunder, each Recipient * hereby assumes sole responsibility to secure any * other intellectual property rights needed, if any. * * For example, if a third party patent license is * required to allow Recipient to distribute the * Program, it is Recipient's responsibility to * acquire that license before distributing the * Program. * * d) Each Contributor represents that to its * knowledge it has sufficient copyright rights in its * Contribution, if any, to grant the copyright * license set forth in this Agreement. * * 3. REQUIREMENTS * * A Contributor may choose to distribute the Program in * object code form under its own license agreement, provided * that: * a) it complies with the terms and conditions of * this Agreement; and * * b) its license agreement: * i) effectively disclaims on behalf of all * Contributors all warranties and conditions, express * and implied, including warranties or conditions of * title and no - infringement, and implied warranties * or conditions of merchantability and fitness for a * particular purpose; * * ii) effectively excludes on behalf of all * Contributors all liability for damages, including * direct, indirect, special, incidental and * consequential damages, such as lost profits; * * iii) states that any provisions which differ from * this Agreement are offered by that Contributor * alone and not by any other party; and * * iv) states that source code for the Program is * available from such Contributor, and informs * licensees how to obtain it in a reasonable manner * on or through a medium customarily used for * software exchange. * * When the Program is made available in source code form: * a) it must be made available under this Agreement; * and * b) a copy of this Agreement must be included with * each copy of the Program. * * Contributors may not remove or alter any copyright notices * contained within the Program. * * Each Contributor must identify itself as the originator of * its Contribution, if any, in a manner that reasonably * allows subsequent Recipients to identify the originator of * the Contribution. * * * 4. COMMERCIAL DISTRIBUTION * * Commercial distributors of software may accept certain * responsibilities with respect to end users, business * partners and the like. While this license is intended to * facilitate the commercial use of the Program, the * Contributor who includes the Program in a commercial * product offering should do so in a manner which does not * create potential liability for other Contributors. * Therefore, if a Contributor includes the Program in a * commercial product offering, such Contributor ("Commercial * Contributor") hereby agrees to defend and indemnify every * other Contributor ("Indemnified Contributor") against any * losses, damages and costs (collectively "Losses") arising * from claims, lawsuits and other legal actions brought by a * third party against the Indemnified Contributor to the * extent caused by the acts or omissions of such Commercial * Contributor in connection with its distribution of the * Program in a commercial product offering. The obligations * in this section do not apply to any claims or Losses * relating to any actual or alleged intellectual property * infringement. In order to qualify, an Indemnified * Contributor must: a) promptly notify the Commercial * Contributor in writing of such claim, and b) allow the * Commercial Contributor to control, and cooperate with the * Commercial Contributor in, the defense and any related * settlement negotiations. The Indemnified Contributor may * participate in any such claim at its own expense. * * * For example, a Contributor might include the Program in a * commercial product offering, Product X. That Contributor * is then a Commercial Contributor. If that Commercial * Contributor then makes performance claims, or offers * warranties related to Product X, those performance claims * and warranties are such Commercial Contributor's * responsibility alone. Under this section, the Commercial * Contributor would have to defend claims against the other * Contributors related to those performance claims and * warranties, and if a court requires any other Contributor * to pay any damages as a result, the Commercial Contributor * must pay those damages. * * * 5. NO WARRANTY * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE * PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR * IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR * CONDITIONS OF TITLE, NO - INFRINGEMENT, MERCHANTABILITY OR * FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely * responsible for determining the appropriateness of using * and distributing the Program and assumes all risks * associated with its exercise of rights under this * Agreement, including but not limited to the risks and * costs of program errors, compliance with applicable laws, * damage to or loss of data, programs or equipment, and * unavailability or interruption of operations. * * 6. DISCLAIMER OF LIABILITY * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER * RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION * LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE * OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * 7. GENERAL * * If any provision of this Agreement is invalid or * unenforceable under applicable law, it shall not affect * the validity or enforceability of the remainder of the * terms of this Agreement, and without further action by the * parties hereto, such provision shall be reformed to the * minimum extent necessary to make such provision valid and * enforceable. * * * If Recipient institutes patent litigation against a * Contributor with respect to a patent applicable to * software (including a cros - claim or counterclaim in a * lawsuit), then any patent licenses granted by that * Contributor to such Recipient under this Agreement shall * terminate as of the date such litigation is filed. In * addition, If Recipient institutes patent litigation * against any entity (including a cros - claim or * counterclaim in a lawsuit) alleging that the Program * itself (excluding combinations of the Program with other * software or hardware) infringes such Recipient's * patent(s), then such Recipient's rights granted under * Section 2(b) shall terminate as of the date such * litigation is filed. * * All Recipient's rights under this Agreement shall * terminate if it fails to comply with any of the material * terms or conditions of this Agreement and does not cure * such failure in a reasonable period of time after becoming * aware of such noncompliance. If all Recipient's rights * under this Agreement terminate, Recipient agrees to cease * use and distribution of the Program as soon as reasonably * practicable. However, Recipient's obligations under this * Agreement and any licenses granted by Recipient relating * to the Program shall continue and survive. * * Everyone is permitted to copy and distribute copies of * this Agreement, but in order to avoid inconsistency the * Agreement is copyrighted and may only be modified in the * following manner. The Agreement Steward reserves the right * to publish new versions (including revisions) of this * Agreement from time to time. No one other than the * Agreement Steward has the right to modify this Agreement. * * IBM is the initial Agreement Steward. IBM may assign the * responsibility to serve as the Agreement Steward to a * suitable separate entity. Each new version of the * Agreement will be given a distinguishing version number. * The Program (including Contributions) may always be * distributed subject to the version of the Agreement under * which it was received. In addition, after a new version of * the Agreement is published, Contributor may elect to * distribute the Program (including its Contributions) under * the new version. Except as expressly stated in Sections * 2(a) and 2(b) above, Recipient receives no rights or * licenses to the intellectual property of any Contributor * under this Agreement, whether expressly, by implication, * estoppel or otherwise. All rights in the Program not * expressly granted under this Agreement are reserved. * * * This Agreement is governed by the laws of the State of New * York and the intellectual property laws of the United * States of America. No party to this Agreement will bring a * legal action under this Agreement more than one year after * the cause of action arose. Each party waives its rights to * a jury trial in any resulting litigation. * * * * (C) COPYRIGHT International Business Machines Corp. 2001, 2002 */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include "tpmtok_int.h" #include #include #include #include void stlogit(char *, ...); extern int debugfile; pthread_mutex_t lmtx = PTHREAD_MUTEX_INITIALIZER; static int enabled = 0; static int logging = 0; static int env_log_check = 0; void stloginit() { char *logval; if (! env_log_check) { logval = getenv("PKCS_ERROR_LOG"); env_log_check = 1; if (logval != NULL) logging = 1; else logging = 0; } if (! enabled && logging) { enabled = 1; openlog((const char *)token_specific.token_debug_tag, LOG_PID | LOG_NDELAY, LOG_LOCAL6); (void) setlogmask(LOG_UPTO(LOG_DEBUG)); #ifdef DEBUG debugfile = 1; #else debugfile = 0; #endif stlogit("Log initialized"); } } void stlogterm() { enabled = 0; } /*PRINTFLIKE2*/ void stlogit2(int type, char *fmt, ...) { va_list pvar; char buffer[4096*4]; if (! enabled) stloginit(); if (enabled && type) { va_start(pvar, fmt); (void) vsnprintf(buffer, sizeof (buffer), fmt, pvar); va_end(pvar); (void) pthread_mutex_lock(&lmtx); syslog(LOG_DEBUG, buffer); (void) pthread_mutex_unlock(&lmtx); } } /*PRINTFLIKE1*/ void stlogit(char *fmt, ...) { va_list pvar; char buffer[4096*4]; if (! enabled) stloginit(); if (enabled && debugfile) { va_start(pvar, fmt); (void) vsnprintf(buffer, sizeof (buffer), fmt, pvar); va_end(pvar); (void) pthread_mutex_lock(&lmtx); syslog(LOG_DEBUG, buffer); (void) pthread_mutex_unlock(&lmtx); } } /* moved in from msg.h */ struct messages err_msg[] = { { "Malloc Failed" }, { "Not Enough Memory in Context" }, { "Slot Invalid" }, { "General Error" }, { "%s Function Failed" }, // #5 { "%s Bad Arguments" }, { "No Event" }, { "Attribute Read Only" }, { "Attribute Type Invalid" }, { "Attribute Value Invalid" }, // #10 { "Data Invalid" }, { "Data Length out of Range" }, { "Device Error" }, { "Device Removed" }, { "Encrypted Data Invalid" }, // 15 { "Encrypted Data Length out of Range" }, { "Function Cancelled" }, { "Function Not Parallel" }, { "Key Handle Invalid" }, { "Key Size out of Range" }, // 20 { "Key Type Inconsistent" }, { "Key Not Needed" }, { "Key Changed" }, { "Key Needed" }, { "Key Indigestible" }, // 25 { "Key Function Not Permitted" }, { "Key Not Wrappable" }, { "Key Unextractable" }, { "Mechanism Invalid" }, { "Mechanism Param Invalid" }, // 30 { "Object Handle Invalid" }, { "Operation Active" }, { "Operation Not Initialized" }, { "Pin Incorrect" }, { "Pin Invalid" }, // 35 { "Pin Length out of Range" }, { "Pin Expired" }, { "Pin Locked" }, { "Session Closed" }, { "Session Count" }, // 40 { "Session Handle Invalid" }, { "Parallel Session Not Supported" }, { "Session Read Only" }, { "Session Exists" }, { "Session Read only Exists" }, // 45 { "Session Read Write Exists" }, { "Signature Length out of Range" }, { "Signature Invalid" }, { "Template Incomplete" }, { "Template Inconsistent" }, // 50 { "Token Not Present" }, { "Token Not Recognized" }, { "Token Write Protected" }, { "Unwrapping Key Handle Invalid" }, { "Unwrapping Key Size Range Invalid" }, // 55 { "Unwrapping Key Type Inconsistent" }, { "User Already Logged In" }, { "User Not Logged In" }, { "User PIN Not Initialized" }, { "User Type Invalid" }, // 60 { "Another User Already Logged In" }, { "Too Many User Types" }, { "Wrapped Key Invalid" }, { "Wrapped Key Length Out of Range" }, { "Wrapping Key Size out of Range" }, // 65 { "Wrapping Key Type Inconsistent" }, { "Random Seed Not Supported" }, { "Random Number Invalid" }, { "Buffer Too Small" }, { "Saved State Invalid" }, // 70 { "Information Sensitive" }, { "State Unsaveable" }, { "API not initialized" }, { "API already Initialized" }, { "Mutex Bad" }, // 75 { "Mutex Lock Invalid" }, { "Encode Integer Failed" }, { "Encode Octet String Failed" }, { "Encode Sequence Failed" }, { "Decode Integer Failed" }, // 80 { "Decode Octet String Failed" }, { "Decode Sequence Failed" }, { "Encode Private Key Failed" }, { "Decode Private Key Failed" }, { "Build Attribute Failed" }, // 85 { "Function Not Permitted" }, { "Key Not Exportable" }, { "Encode Private Key failed" }, { "Decode Private Key failed" }, { "Object Mgr Create Skeleton failed" }, // 90 { "Object Mgr Create Final failed" }, { "Key Generation failed" }, { "DES Wrap Get Data Failed" }, { "DES3 Wrap Get Data Failed" }, { "RSA Wrap Get Data Failed" }, // 95 { "DSA Wrap Get Data Failed" }, { "Generic Secret Wrap Get Data Failed" }, { "DES Wrap Format Failed" }, { "Encryption Mgr Init Failed" }, { "Encryption Mgr Encrypt Failed" }, // 100 { "Decryption Mgr Decrypt Failed" }, { "Flatten Object Failed" }, { "Key Mgr Get Priv Key Type Failed" }, { "Decrypt Private Key Info Failed" }, { "Save Token Failed" }, // 105 { "Triple DES CBC Encrypt Failed" }, { "Triple DES CBC Decrypt Failed" }, { "Restore Private Token Failed" }, { "Restore Object Failed" }, { "Data Length Out of Range" }, // 110 { "Object Manager Find in Map Failed" }, { "Token Specific RNG Failed" }, { "Encrypted Data Length Out of Range" }, { "DES CBC Encrypt Failed" }, { "DES CBC Decrypt Failed" }, // 115 { "DES ECB Encrypt Failed" }, { "DES ECB Decrypt Failed" }, { "Token Specific DES ECB Failed" }, { "Token Specific DES CBC Failed" }, { "Token Specific 3DES CBC Failed" }, // 120 { "Token Specific 3DES ECB Failed" }, { "DSA Verify Failed" }, { "DSA Sign Failed" }, { "Digest Init Failed" }, { "Digest Failed" }, // 125 { "Digest Update Failed" }, { "Digest Final Failed" }, { "Sign Init Failed" }, { "Sign Update Failed" }, { "Sign Final Failed" }, // 130 { "Random Number Generate Failed" }, { "RSA Format Block Failed" }, { "RSA Encrypt Failed" }, { "RSA Decrypt Failed" }, { "Token Specific RSA Encrypt Failed" }, // 135 { "Token Specific RSA Decrypt Failed" }, { "SSL SHA Failed" }, { "SSL3 MD5 Failed" }, { "SSL3 Process MAC Keys Failed" }, { "SSL3 Process Write Keys Failed" }, // 140 { "Validate Attribute Failed" }, { "SSL3 Process Write Keys Failed" }, { "%s Function Not Supported" }, { "Token Already Initialized" }, { "Cannot Attach to Shared Memory" }, // 145 { "Token Specific Init Failed" }, { "Mutex Lock Failed" }, { "Mutex Unlock Failed" }, { "Hash Computation Failed" }, { "Save Master Key Failed" }, // 150 { "Process Lock Failed" }, { "Process Unlock Failed" }, { "Session Mgr New Failed" }, { "Close all Sessions Failed" }, { "Session Mgr Get Op State Failed" }, // 155 { "Load Master Key Failed" }, { "Object Create Failed" }, { "Object Mgr Add to Map Failed" }, { "Object Copy Failed" }, { "Object Get Attribute Values Failed" }, // 160 { "Object Restore Data Failed" }, { "Object Set Attribute Values Failed" }, { "Object Mgr Search for Object Failed" }, { "Copy Template Failed" }, { "Add Attribute Failed" }, // 165 { "Check Required Attributes Failed" }, { "Unflatten Template Failed" }, { "Verify Init Failed" }, { "Verify Failed" }, { "Verify Update Failed" }, // 170 { "Verify Final Failed" }, { "Sign Failed" }, { "Set Default Attributes Failed" }, { "Unwrap Key Failed" }, { "Session Mgr New Failed" }, // 175 { "Merge Attributes Failed" }, { "Encryption Mgr Encrypt Update Failed" }, { "Encryption Mgr Encrypt Final Failed" }, { "Update Attribute Failed" }, { "Decryption Mgr Init Failed" }, // 180 { "Decryption Mgr Update Failed" }, { "Decryption Mgr Final Failed" }, { "Object Mgr Destroy Failed" }, { "Attribute Undefined" }, { "Object Mgr Get Size Failed" }, // 185 { "Object Manager Find Init Failed" }, { "Sign Recover Failed" }, { "Verify Recover Failed" }, { "Wrap Key Failed" }, { "Unwrap Key Failed" }, // 190 { "Derive Key Failed" }, { "AES Wrap Get Data Failed" }, { "AES Wrap Format Failed" }, { "Domain Parameter Invalid" }, { "File \"%s\" could not be opened, errno =%d" } }; # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. # # MAPFILE HEADER START # # WARNING: STOP NOW. DO NOT MODIFY THIS FILE. # Object versioning must comply with the rules detailed in # # usr/src/lib/README.mapfiles # # You should not be making modifications here until you've read the most current # copy of that file. If you need help, contact a gatekeeper for guidance. # # MAPFILE HEADER END # $mapfile_version 2 SYMBOL_VERSION SUNW_1.1 { global: C_CancelFunction; C_CloseAllSessions; C_CloseSession; C_CopyObject; C_CreateObject; C_Decrypt; C_DecryptDigestUpdate; C_DecryptFinal; C_DecryptInit; C_DecryptUpdate; C_DecryptVerifyUpdate; C_DeriveKey; C_DestroyObject; C_Digest; C_DigestEncryptUpdate; C_DigestFinal; C_DigestInit; C_DigestKey; C_DigestUpdate; C_Encrypt; C_EncryptFinal; C_EncryptInit; C_EncryptUpdate; C_Finalize; C_FindObjects; C_FindObjectsFinal; C_FindObjectsInit; C_GenerateKey; C_GenerateKeyPair; C_GenerateRandom; C_GetAttributeValue; C_GetFunctionList; C_GetFunctionStatus; C_GetInfo; C_GetMechanismInfo; C_GetMechanismList; C_GetObjectSize; C_GetOperationState; C_GetSessionInfo; C_GetSlotInfo; C_GetSlotList; C_GetTokenInfo; C_Initialize; C_InitPIN; C_InitToken; C_Login; C_Logout; C_OpenSession; C_SeedRandom; C_SetAttributeValue; C_SetOperationState; C_SetPIN; C_Sign; C_SignEncryptUpdate; C_SignFinal; C_SignInit; C_SignRecover; C_SignRecoverInit; C_SignUpdate; C_UnwrapKey; C_Verify; C_VerifyFinal; C_VerifyInit; C_VerifyRecover; C_VerifyRecoverInit; C_VerifyUpdate; C_WaitForSlotEvent; C_WrapKey; local: *; }; /* * 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 */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include "tpmtok_int.h" CK_RV md5_hash(SESSION *sess, CK_BBOOL length_only, DIGEST_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { if (! sess || ! ctx || ! out_data_len) { return (CKR_FUNCTION_FAILED); } *out_data_len = MD5_DIGEST_LENGTH; if (length_only == TRUE) { return (CKR_OK); } MD5Update(ctx->context.md5ctx, in_data, in_data_len); MD5Final(out_data, ctx->context.md5ctx); return (CKR_OK); } CK_RV md5_hmac_sign(SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len) { OBJECT * key_obj = NULL; CK_ATTRIBUTE * attr = NULL; CK_BYTE hash[MD5_DIGEST_LENGTH]; DIGEST_CONTEXT digest_ctx; CK_MECHANISM digest_mech; CK_BYTE k_ipad[MD5_BLOCK_SIZE]; CK_BYTE k_opad[MD5_BLOCK_SIZE]; CK_ULONG key_bytes, hash_len, hmac_len; CK_ULONG i; CK_RV rc; if (! sess || ! ctx || ! out_data_len) { return (CKR_FUNCTION_FAILED); } if (ctx->mech.mechanism == CKM_MD5_HMAC_GENERAL) { hmac_len = *(CK_ULONG *)ctx->mech.pParameter; if (hmac_len == 0) { *out_data_len = 0; return (CKR_OK); } } else hmac_len = MD5_DIGEST_LENGTH; *out_data_len = hmac_len; if (length_only == TRUE) { return (CKR_OK); } (void) memset(&digest_ctx, 0x0, sizeof (DIGEST_CONTEXT)); rc = object_mgr_find_in_map1(sess->hContext, ctx->key, &key_obj); if (rc != CKR_OK) return (rc); rc = template_attribute_find(key_obj->template, CKA_VALUE, &attr); if (rc == FALSE) { return (CKR_FUNCTION_FAILED); } else key_bytes = attr->ulValueLen; // build (K XOR ipad), (K XOR opad) // if (key_bytes > MD5_BLOCK_SIZE) { digest_mech.mechanism = CKM_MD5; digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; rc = digest_mgr_init(sess, &digest_ctx, &digest_mech); if (rc != CKR_OK) { (void) digest_mgr_cleanup(&digest_ctx); return (rc); } hash_len = *out_data_len; rc = digest_mgr_digest(sess, FALSE, &digest_ctx, attr->pValue, attr->ulValueLen, hash, &hash_len); if (rc != CKR_OK) { (void) digest_mgr_cleanup(&digest_ctx); return (rc); } (void) digest_mgr_cleanup(&digest_ctx); (void) memset(&digest_ctx, 0x0, sizeof (DIGEST_CONTEXT)); for (i = 0; i < hash_len; i++) { k_ipad[i] = hash[i] ^ 0x36; k_opad[i] = hash[i] ^ 0x5C; } (void) memset(&k_ipad[i], 0x36, MD5_BLOCK_SIZE - i); (void) memset(&k_opad[i], 0x5C, MD5_BLOCK_SIZE - i); } else { CK_BYTE *key = attr->pValue; for (i = 0; i < key_bytes; i++) { k_ipad[i] = key[i] ^ 0x36; k_opad[i] = key[i] ^ 0x5C; } (void) memset(&k_ipad[i], 0x36, MD5_BLOCK_SIZE - key_bytes); (void) memset(&k_opad[i], 0x5C, MD5_BLOCK_SIZE - key_bytes); } digest_mech.mechanism = CKM_MD5; digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; rc = digest_mgr_init(sess, &digest_ctx, &digest_mech); if (rc != CKR_OK) { (void) digest_mgr_cleanup(&digest_ctx); return (rc); } rc = digest_mgr_digest_update(sess, &digest_ctx, k_ipad, MD5_BLOCK_SIZE); if (rc != CKR_OK) { (void) digest_mgr_cleanup(&digest_ctx); return (rc); } rc = digest_mgr_digest_update(sess, &digest_ctx, in_data, in_data_len); if (rc != CKR_OK) { (void) digest_mgr_cleanup(&digest_ctx); return (rc); } hash_len = sizeof (hash); rc = digest_mgr_digest_final(sess, &digest_ctx, hash, &hash_len); if (rc != CKR_OK) { (void) digest_mgr_cleanup(&digest_ctx); return (rc); } (void) digest_mgr_cleanup(&digest_ctx); (void) memset(&digest_ctx, 0x0, sizeof (DIGEST_CONTEXT)); rc = digest_mgr_init(sess, &digest_ctx, &digest_mech); if (rc != CKR_OK) { (void) digest_mgr_cleanup(&digest_ctx); return (rc); } rc = digest_mgr_digest_update(sess, &digest_ctx, k_opad, MD5_BLOCK_SIZE); if (rc != CKR_OK) { (void) digest_mgr_cleanup(&digest_ctx); return (rc); } rc = digest_mgr_digest_update(sess, &digest_ctx, hash, hash_len); if (rc != CKR_OK) { (void) digest_mgr_cleanup(&digest_ctx); return (rc); } hash_len = sizeof (hash); rc = digest_mgr_digest_final(sess, &digest_ctx, hash, &hash_len); if (rc != CKR_OK) { (void) digest_mgr_cleanup(&digest_ctx); return (rc); } (void) memcpy(out_data, hash, hmac_len); *out_data_len = hmac_len; (void) digest_mgr_cleanup(&digest_ctx); return (CKR_OK); } CK_RV md5_hmac_verify(SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * signature, CK_ULONG sig_len) { CK_BYTE hmac[MD5_DIGEST_LENGTH]; SIGN_VERIFY_CONTEXT hmac_ctx; CK_ULONG hmac_len, len; CK_RV rc; if (! sess || ! ctx || ! in_data || ! signature) { return (CKR_FUNCTION_FAILED); } if (ctx->mech.mechanism == CKM_MD5_HMAC_GENERAL) hmac_len = *(CK_ULONG *)ctx->mech.pParameter; else hmac_len = MD5_DIGEST_LENGTH; (void) memset(&hmac_ctx, 0, sizeof (SIGN_VERIFY_CONTEXT)); rc = sign_mgr_init(sess, &hmac_ctx, &ctx->mech, FALSE, ctx->key); if (rc != CKR_OK) { (void) sign_mgr_cleanup(&hmac_ctx); return (rc); } len = sizeof (hmac); rc = sign_mgr_sign(sess, FALSE, &hmac_ctx, in_data, in_data_len, hmac, &len); if (rc != CKR_OK) { (void) sign_mgr_cleanup(&hmac_ctx); return (rc); } if ((len != hmac_len) || (len != sig_len)) { return (CKR_SIGNATURE_LEN_RANGE); } if (memcmp(hmac, signature, hmac_len) != 0) { rc = CKR_SIGNATURE_INVALID; } (void) sign_mgr_cleanup(&hmac_ctx); return (rc); } /* * The Initial Developer of the Original Code is International * Business Machines Corporation. Portions created by IBM * Corporation are Copyright (C) 2005 International Business * Machines Corporation. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the Common Public License as published by * IBM Corporation; either version 1 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * Common Public License for more details. * * You should have received a copy of the Common Public License * along with this program; if not, a copy can be viewed at * http://www.opensource.org/licenses/cpl1.0.php. */ /* (C) COPYRIGHT International Business Machines Corp. 2001, 2002, 2005 */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include "tpmtok_int.h" extern CK_RV token_specific_rsa_verify_recover( TSS_HCONTEXT hContext, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key_obj); CK_RV ckm_rsa_key_pair_gen(TSS_HCONTEXT hContext, TEMPLATE * publ_tmpl, TEMPLATE * priv_tmpl) { CK_RV rc; rc = token_specific.t_rsa_generate_keypair( hContext, publ_tmpl, priv_tmpl); return (rc); } static CK_RV ckm_rsa_encrypt( TSS_HCONTEXT hContext, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, OBJECT * key_obj) { CK_ATTRIBUTE * attr = NULL; CK_OBJECT_CLASS keyclass; CK_RV rc; rc = template_attribute_find(key_obj->template, CKA_CLASS, &attr); if (rc == FALSE) { return (CKR_FUNCTION_FAILED); } else keyclass = *(CK_OBJECT_CLASS *)attr->pValue; if (keyclass != CKO_PUBLIC_KEY) { return (CKR_FUNCTION_FAILED); } rc = token_specific.t_rsa_encrypt(hContext, in_data, in_data_len, out_data, out_data_len, key_obj); return (rc); } static CK_RV ckm_rsa_decrypt( TSS_HCONTEXT hContext, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, OBJECT * key_obj) { CK_ATTRIBUTE * attr = NULL; CK_OBJECT_CLASS keyclass; CK_RV rc; rc = template_attribute_find(key_obj->template, CKA_CLASS, &attr); if (rc == FALSE) { return (CKR_FUNCTION_FAILED); } else keyclass = *(CK_OBJECT_CLASS *)attr->pValue; // this had better be a private key // if (keyclass != CKO_PRIVATE_KEY) { return (CKR_FUNCTION_FAILED); } rc = token_specific.t_rsa_decrypt(hContext, in_data, in_data_len, out_data, out_data_len, key_obj); return (rc); } static CK_RV ckm_rsa_sign( TSS_HCONTEXT hContext, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, OBJECT * key_obj) { CK_ATTRIBUTE * attr = NULL; CK_OBJECT_CLASS keyclass; CK_RV rc; rc = template_attribute_find(key_obj->template, CKA_CLASS, &attr); if (rc == FALSE) { return (CKR_FUNCTION_FAILED); } else { keyclass = *(CK_OBJECT_CLASS *)attr->pValue; } if (keyclass != CKO_PRIVATE_KEY) { return (CKR_FUNCTION_FAILED); } rc = token_specific.t_rsa_sign( hContext, in_data, in_data_len, out_data, out_data_len, key_obj); return (rc); } static CK_RV ckm_rsa_verify( TSS_HCONTEXT hContext, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG out_data_len, OBJECT * key_obj) { CK_ATTRIBUTE * attr = NULL; CK_OBJECT_CLASS keyclass; CK_RV rc; rc = template_attribute_find(key_obj->template, CKA_CLASS, &attr); if (rc == FALSE) { return (CKR_FUNCTION_FAILED); } else keyclass = *(CK_OBJECT_CLASS *)attr->pValue; if (keyclass != CKO_PUBLIC_KEY) { return (CKR_FUNCTION_FAILED); } rc = token_specific.t_rsa_verify(hContext, in_data, in_data_len, out_data, out_data_len, key_obj); return (rc); } /*ARGSUSED*/ CK_RV rsa_pkcs_encrypt(SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { OBJECT *key_obj = NULL; CK_ATTRIBUTE *attr = NULL; CK_ULONG modulus_bytes; CK_BBOOL flag; CK_RV rc; rc = object_mgr_find_in_map1(sess->hContext, ctx->key, &key_obj); if (rc != CKR_OK) { return (rc); } flag = template_attribute_find(key_obj->template, CKA_MODULUS, &attr); if (flag == FALSE) { return (CKR_FUNCTION_FAILED); } else { modulus_bytes = attr->ulValueLen; } if (length_only == TRUE) { *out_data_len = modulus_bytes; return (CKR_OK); } if (*out_data_len < modulus_bytes) { *out_data_len = modulus_bytes; return (CKR_BUFFER_TOO_SMALL); } rc = ckm_rsa_encrypt(sess->hContext, in_data, in_data_len, out_data, out_data_len, key_obj); return (rc); } /*ARGSUSED*/ CK_RV rsa_pkcs_decrypt(SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { OBJECT *key_obj = NULL; CK_ATTRIBUTE *attr = NULL; CK_ULONG modulus_bytes; CK_BBOOL flag; CK_RV rc; rc = object_mgr_find_in_map1(sess->hContext, ctx->key, &key_obj); if (rc != CKR_OK) { return (rc); } flag = template_attribute_find(key_obj->template, CKA_MODULUS, &attr); if (flag == FALSE) return (CKR_FUNCTION_FAILED); else modulus_bytes = attr->ulValueLen; if (in_data_len != modulus_bytes) { return (CKR_ENCRYPTED_DATA_LEN_RANGE); } if (length_only == TRUE) { *out_data_len = modulus_bytes - 11; return (CKR_OK); } rc = ckm_rsa_decrypt(sess->hContext, in_data, modulus_bytes, out_data, out_data_len, key_obj); if (rc == CKR_DATA_LEN_RANGE) { return (CKR_ENCRYPTED_DATA_LEN_RANGE); } return (rc); } CK_RV rsa_pkcs_sign(SESSION *sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { OBJECT *key_obj = NULL; CK_ATTRIBUTE *attr = NULL; CK_ULONG modulus_bytes; CK_BBOOL flag; CK_RV rc; if (! sess || ! ctx || ! out_data_len) { return (CKR_FUNCTION_FAILED); } rc = object_mgr_find_in_map1(sess->hContext, ctx->key, &key_obj); if (rc != CKR_OK) { return (rc); } flag = template_attribute_find(key_obj->template, CKA_MODULUS, &attr); if (flag == FALSE) return (CKR_FUNCTION_FAILED); else modulus_bytes = attr->ulValueLen; if (length_only == TRUE) { *out_data_len = modulus_bytes; return (CKR_OK); } if (*out_data_len < modulus_bytes) { *out_data_len = modulus_bytes; return (CKR_BUFFER_TOO_SMALL); } rc = ckm_rsa_sign(sess->hContext, in_data, in_data_len, out_data, out_data_len, key_obj); return (rc); } /*ARGSUSED*/ CK_RV rsa_pkcs_verify(SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * signature, CK_ULONG sig_len) { OBJECT *key_obj = NULL; CK_ATTRIBUTE *attr = NULL; CK_ULONG modulus_bytes; CK_BBOOL flag; CK_RV rc; rc = object_mgr_find_in_map1(sess->hContext, ctx->key, &key_obj); if (rc != CKR_OK) { return (rc); } flag = template_attribute_find(key_obj->template, CKA_MODULUS, &attr); if (flag == FALSE) { return (CKR_FUNCTION_FAILED); } else modulus_bytes = attr->ulValueLen; // check input data length restrictions // if (sig_len != modulus_bytes) { return (CKR_SIGNATURE_LEN_RANGE); } // verify is a public key operation --> encrypt // rc = ckm_rsa_verify(sess->hContext, in_data, in_data_len, signature, sig_len, key_obj); return (rc); } CK_RV rsa_pkcs_verify_recover(SESSION *sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *signature, CK_ULONG sig_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { OBJECT *key_obj = NULL; CK_ATTRIBUTE *attr = NULL; CK_ULONG modulus_bytes; CK_BBOOL flag; CK_RV rc; if (! sess || ! ctx || ! out_data_len) { return (CKR_FUNCTION_FAILED); } rc = object_mgr_find_in_map1(sess->hContext, ctx->key, &key_obj); if (rc != CKR_OK) { return (rc); } flag = template_attribute_find(key_obj->template, CKA_MODULUS, &attr); if (flag == FALSE) { return (CKR_FUNCTION_FAILED); } else modulus_bytes = attr->ulValueLen; if (sig_len != modulus_bytes) { return (CKR_SIGNATURE_LEN_RANGE); } if (length_only == TRUE) { *out_data_len = modulus_bytes; return (CKR_OK); } rc = token_specific_rsa_verify_recover(sess->hContext, signature, modulus_bytes, out_data, out_data_len, key_obj); return (rc); } CK_RV rsa_hash_pkcs_sign(SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * signature, CK_ULONG * sig_len) { CK_BYTE * ber_data = NULL; CK_BYTE * octet_str = NULL; CK_BYTE * oid = NULL; CK_BYTE * tmp = NULL; CK_ULONG buf1[16]; CK_BYTE hash[SHA1_DIGEST_LENGTH]; DIGEST_CONTEXT digest_ctx; SIGN_VERIFY_CONTEXT sign_ctx; CK_MECHANISM digest_mech; CK_MECHANISM sign_mech; CK_ULONG ber_data_len, hash_len, octet_str_len, oid_len; CK_RV rc; if (! sess || ! ctx || ! in_data) { return (CKR_FUNCTION_FAILED); } (void) memset(&digest_ctx, 0x0, sizeof (digest_ctx)); (void) memset(&sign_ctx, 0x0, sizeof (sign_ctx)); if (ctx->mech.mechanism == CKM_MD5_RSA_PKCS) { digest_mech.mechanism = CKM_MD5; oid = ber_AlgMd5; oid_len = ber_AlgMd5Len; hash_len = MD5_DIGEST_LENGTH; } else { digest_mech.mechanism = CKM_SHA_1; oid = ber_AlgSha1; oid_len = ber_AlgSha1Len; hash_len = SHA1_DIGEST_LENGTH; } digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; rc = digest_mgr_init(sess, &digest_ctx, &digest_mech); if (rc != CKR_OK) { goto error; } rc = digest_mgr_digest(sess, length_only, &digest_ctx, in_data, in_data_len, hash, &hash_len); if (rc != CKR_OK) goto error; rc = ber_encode_OCTET_STRING(FALSE, &octet_str, &octet_str_len, hash, hash_len); if (rc != CKR_OK) { goto error; } tmp = (CK_BYTE *)buf1; (void) memcpy(tmp, oid, oid_len); (void) memcpy(tmp + oid_len, octet_str, octet_str_len); rc = ber_encode_SEQUENCE(FALSE, &ber_data, &ber_data_len, tmp, (oid_len + octet_str_len)); if (rc != CKR_OK) goto error; sign_mech.mechanism = CKM_RSA_PKCS; sign_mech.ulParameterLen = 0; sign_mech.pParameter = NULL; rc = sign_mgr_init(sess, &sign_ctx, &sign_mech, FALSE, ctx->key); if (rc != CKR_OK) goto error; rc = sign_mgr_sign(sess, length_only, &sign_ctx, ber_data, ber_data_len, signature, sig_len); error: if (octet_str) free(octet_str); if (ber_data) free(ber_data); (void) digest_mgr_cleanup(&digest_ctx); (void) sign_mgr_cleanup(&sign_ctx); return (rc); } CK_RV rsa_hash_pkcs_sign_update( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len) { RSA_DIGEST_CONTEXT * context = NULL; CK_MECHANISM digest_mech; CK_RV rc; if (! sess || ! ctx || ! in_data) return (CKR_FUNCTION_FAILED); context = (RSA_DIGEST_CONTEXT *)ctx->context; if (context->flag == FALSE) { if (ctx->mech.mechanism == CKM_MD5_RSA_PKCS) digest_mech.mechanism = CKM_MD5; else digest_mech.mechanism = CKM_SHA_1; digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; rc = digest_mgr_init(sess, &context->hash_context, &digest_mech); if (rc != CKR_OK) { goto error; } context->flag = TRUE; } rc = digest_mgr_digest_update(sess, &context->hash_context, in_data, in_data_len); if (rc != CKR_OK) { goto error; } return (CKR_OK); error: (void) digest_mgr_cleanup(&context->hash_context); return (rc); } CK_RV rsa_hash_pkcs_verify(SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * signature, CK_ULONG sig_len) { CK_BYTE * ber_data = NULL; CK_BYTE * octet_str = NULL; CK_BYTE * oid = NULL; CK_BYTE * tmp = NULL; CK_ULONG buf1[16]; CK_BYTE hash[SHA1_DIGEST_LENGTH]; DIGEST_CONTEXT digest_ctx; SIGN_VERIFY_CONTEXT verify_ctx; CK_MECHANISM digest_mech; CK_MECHANISM verify_mech; CK_ULONG ber_data_len, hash_len, octet_str_len, oid_len; CK_RV rc; if (! sess || ! ctx || ! in_data) { return (CKR_FUNCTION_FAILED); } (void) memset(&digest_ctx, 0x0, sizeof (digest_ctx)); (void) memset(&verify_ctx, 0x0, sizeof (verify_ctx)); if (ctx->mech.mechanism == CKM_MD5_RSA_PKCS) { digest_mech.mechanism = CKM_MD5; oid = ber_AlgMd5; oid_len = ber_AlgMd5Len; hash_len = MD5_DIGEST_LENGTH; } else { digest_mech.mechanism = CKM_SHA_1; oid = ber_AlgSha1; oid_len = ber_AlgSha1Len; hash_len = SHA1_DIGEST_LENGTH; } digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; rc = digest_mgr_init(sess, &digest_ctx, &digest_mech); if (rc != CKR_OK) { goto done; } rc = digest_mgr_digest(sess, FALSE, &digest_ctx, in_data, in_data_len, hash, &hash_len); if (rc != CKR_OK) { goto done; } rc = ber_encode_OCTET_STRING(FALSE, &octet_str, &octet_str_len, hash, hash_len); if (rc != CKR_OK) goto done; tmp = (CK_BYTE *)buf1; (void) memcpy(tmp, oid, oid_len); (void) memcpy(tmp + oid_len, octet_str, octet_str_len); rc = ber_encode_SEQUENCE(FALSE, &ber_data, &ber_data_len, tmp, (oid_len + octet_str_len)); if (rc != CKR_OK) { goto done; } verify_mech.mechanism = CKM_RSA_PKCS; verify_mech.ulParameterLen = 0; verify_mech.pParameter = NULL; rc = verify_mgr_init(sess, &verify_ctx, &verify_mech, FALSE, ctx->key); if (rc != CKR_OK) { goto done; } rc = verify_mgr_verify(sess, &verify_ctx, ber_data, ber_data_len, signature, sig_len); done: if (octet_str) free(octet_str); if (ber_data) free(ber_data); (void) digest_mgr_cleanup(&digest_ctx); (void) sign_mgr_cleanup(&verify_ctx); return (rc); } CK_RV rsa_hash_pkcs_verify_update(SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE *in_data, CK_ULONG in_data_len) { RSA_DIGEST_CONTEXT * context = NULL; CK_MECHANISM digest_mech; CK_RV rc; if (! sess || ! ctx || ! in_data) { return (CKR_FUNCTION_FAILED); } context = (RSA_DIGEST_CONTEXT *)ctx->context; if (context->flag == FALSE) { if (ctx->mech.mechanism == CKM_MD5_RSA_PKCS) digest_mech.mechanism = CKM_MD5; else digest_mech.mechanism = CKM_SHA_1; digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; rc = digest_mgr_init(sess, &context->hash_context, &digest_mech); if (rc != CKR_OK) goto error; context->flag = TRUE; } rc = digest_mgr_digest_update(sess, &context->hash_context, in_data, in_data_len); if (rc != CKR_OK) goto error; return (CKR_OK); error: (void) digest_mgr_cleanup(&context->hash_context); return (rc); } CK_RV rsa_hash_pkcs_sign_final(SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * signature, CK_ULONG * sig_len) { CK_BYTE * ber_data = NULL; CK_BYTE * octet_str = NULL; CK_BYTE * oid = NULL; CK_BYTE * tmp = NULL; CK_ULONG buf1[16]; CK_BYTE hash[SHA1_DIGEST_LENGTH]; RSA_DIGEST_CONTEXT * context = NULL; CK_ULONG ber_data_len, hash_len, octet_str_len, oid_len; CK_MECHANISM sign_mech; SIGN_VERIFY_CONTEXT sign_ctx; CK_RV rc; if (! sess || ! ctx || ! sig_len) { return (CKR_FUNCTION_FAILED); } if (ctx->mech.mechanism == CKM_MD5_RSA_PKCS) { oid = ber_AlgMd5; oid_len = ber_AlgMd5Len; hash_len = MD5_DIGEST_LENGTH; } else { oid = ber_AlgSha1; oid_len = ber_AlgSha1Len; hash_len = SHA1_DIGEST_LENGTH; } (void) memset(&sign_ctx, 0x0, sizeof (sign_ctx)); context = (RSA_DIGEST_CONTEXT *)ctx->context; rc = digest_mgr_digest_final(sess, &context->hash_context, hash, &hash_len); if (rc != CKR_OK) { goto done; } rc = ber_encode_OCTET_STRING(FALSE, &octet_str, &octet_str_len, hash, hash_len); if (rc != CKR_OK) { goto done; } tmp = (CK_BYTE *)buf1; (void) memcpy(tmp, oid, oid_len); (void) memcpy(tmp + oid_len, octet_str, octet_str_len); rc = ber_encode_SEQUENCE(FALSE, &ber_data, &ber_data_len, tmp, (oid_len + octet_str_len)); if (rc != CKR_OK) { goto done; } sign_mech.mechanism = CKM_RSA_PKCS; sign_mech.ulParameterLen = 0; sign_mech.pParameter = NULL; rc = sign_mgr_init(sess, &sign_ctx, &sign_mech, FALSE, ctx->key); if (rc != CKR_OK) { goto done; } rc = sign_mgr_sign(sess, length_only, &sign_ctx, ber_data, ber_data_len, signature, sig_len); if (length_only == TRUE || rc == CKR_BUFFER_TOO_SMALL) { (void) sign_mgr_cleanup(&sign_ctx); return (rc); } done: if (octet_str) free(octet_str); if (ber_data) free(ber_data); (void) digest_mgr_cleanup(&context->hash_context); (void) sign_mgr_cleanup(&sign_ctx); return (rc); } CK_RV rsa_hash_pkcs_verify_final(SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * signature, CK_ULONG sig_len) { CK_BYTE * ber_data = NULL; CK_BYTE * octet_str = NULL; CK_BYTE * oid = NULL; CK_BYTE * tmp = NULL; CK_ULONG buf1[16]; CK_BYTE hash[SHA1_DIGEST_LENGTH]; RSA_DIGEST_CONTEXT * context = NULL; CK_ULONG ber_data_len, hash_len, octet_str_len, oid_len; CK_MECHANISM verify_mech; SIGN_VERIFY_CONTEXT verify_ctx; CK_RV rc; if (! sess || ! ctx || ! signature) { return (CKR_FUNCTION_FAILED); } if (ctx->mech.mechanism == CKM_MD5_RSA_PKCS) { oid = ber_AlgMd5; oid_len = ber_AlgMd5Len; hash_len = MD5_DIGEST_LENGTH; } else { oid = ber_AlgSha1; oid_len = ber_AlgSha1Len; hash_len = SHA1_DIGEST_LENGTH; } (void) memset(&verify_ctx, 0x0, sizeof (verify_ctx)); context = (RSA_DIGEST_CONTEXT *)ctx->context; rc = digest_mgr_digest_final(sess, &context->hash_context, hash, &hash_len); if (rc != CKR_OK) { goto done; } rc = ber_encode_OCTET_STRING(FALSE, &octet_str, &octet_str_len, hash, hash_len); if (rc != CKR_OK) { goto done; } tmp = (CK_BYTE *)buf1; (void) memcpy(tmp, oid, oid_len); (void) memcpy(tmp + oid_len, octet_str, octet_str_len); rc = ber_encode_SEQUENCE(FALSE, &ber_data, &ber_data_len, tmp, (oid_len + octet_str_len)); if (rc != CKR_OK) { goto done; } verify_mech.mechanism = CKM_RSA_PKCS; verify_mech.ulParameterLen = 0; verify_mech.pParameter = NULL; rc = verify_mgr_init(sess, &verify_ctx, &verify_mech, FALSE, ctx->key); if (rc != CKR_OK) { goto done; } rc = verify_mgr_verify(sess, &verify_ctx, ber_data, ber_data_len, signature, sig_len); done: if (octet_str) free(octet_str); if (ber_data) free(ber_data); (void) digest_mgr_cleanup(&context->hash_context); (void) verify_mgr_cleanup(&verify_ctx); return (rc); } /* * The Initial Developer of the Original Code is International * Business Machines Corporation. Portions created by IBM * Corporation are Copyright (C) 2005 International Business * Machines Corporation. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the Common Public License as published by * IBM Corporation; either version 1 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * Common Public License for more details. * * You should have received a copy of the Common Public License * along with this program; if not, a copy can be viewed at * http://www.opensource.org/licenses/cpl1.0.php. */ /* (C) COPYRIGHT International Business Machines Corp. 2001, 2002, 2005 */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include "tpmtok_int.h" CK_RV sha1_hash(SESSION *sess, CK_BBOOL length_only, DIGEST_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { if (! sess || ! ctx || ! out_data_len) { return (CKR_FUNCTION_FAILED); } *out_data_len = SHA1_DIGEST_LENGTH; if (length_only == TRUE) { return (CKR_OK); } if (ctx->context.sha1ctx == NULL) return (CKR_HOST_MEMORY); SHA1Update(ctx->context.sha1ctx, in_data, in_data_len); SHA1Final(out_data, ctx->context.sha1ctx); return (CKR_OK); } CK_RV sha1_hmac_sign(SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len) { OBJECT * key_obj = NULL; CK_ATTRIBUTE * attr = NULL; CK_BYTE hash[SHA1_DIGEST_LENGTH]; DIGEST_CONTEXT digest_ctx; CK_MECHANISM digest_mech; CK_BYTE k_ipad[SHA1_BLOCK_SIZE]; CK_BYTE k_opad[SHA1_BLOCK_SIZE]; CK_ULONG key_bytes, hash_len, hmac_len; CK_ULONG i; CK_RV rc; if (! sess || ! ctx || ! out_data_len) { return (CKR_FUNCTION_FAILED); } if (ctx->mech.mechanism == CKM_SHA_1_HMAC_GENERAL) { hmac_len = *(CK_ULONG *)ctx->mech.pParameter; if (hmac_len == 0) { *out_data_len = 0; return (CKR_OK); } } else { hmac_len = SHA1_DIGEST_LENGTH; } *out_data_len = hmac_len; if (length_only == TRUE) { return (CKR_OK); } (void) memset(&digest_ctx, 0x0, sizeof (DIGEST_CONTEXT)); rc = object_mgr_find_in_map1(sess->hContext, ctx->key, &key_obj); if (rc != CKR_OK) { return (rc); } rc = template_attribute_find(key_obj->template, CKA_VALUE, &attr); if (rc == FALSE) { return (CKR_FUNCTION_FAILED); } else key_bytes = attr->ulValueLen; if (key_bytes > SHA1_BLOCK_SIZE) { digest_mech.mechanism = CKM_SHA_1; digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; rc = digest_mgr_init(sess, &digest_ctx, &digest_mech); if (rc != CKR_OK) { (void) digest_mgr_cleanup(&digest_ctx); return (rc); } hash_len = sizeof (hash); rc = digest_mgr_digest(sess, FALSE, &digest_ctx, attr->pValue, attr->ulValueLen, hash, &hash_len); if (rc != CKR_OK) { (void) digest_mgr_cleanup(&digest_ctx); return (rc); } (void) digest_mgr_cleanup(&digest_ctx); (void) memset(&digest_ctx, 0x0, sizeof (DIGEST_CONTEXT)); for (i = 0; i < hash_len; i++) { k_ipad[i] = hash[i] ^ 0x36; k_opad[i] = hash[i] ^ 0x5C; } (void) memset(&k_ipad[i], 0x36, SHA1_BLOCK_SIZE - i); (void) memset(&k_opad[i], 0x5C, SHA1_BLOCK_SIZE - i); } else { CK_BYTE *key = attr->pValue; for (i = 0; i < key_bytes; i++) { k_ipad[i] = key[i] ^ 0x36; k_opad[i] = key[i] ^ 0x5C; } (void) memset(&k_ipad[i], 0x36, SHA1_BLOCK_SIZE - key_bytes); (void) memset(&k_opad[i], 0x5C, SHA1_BLOCK_SIZE - key_bytes); } digest_mech.mechanism = CKM_SHA_1; digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; if (rc != CKR_OK) { (void) digest_mgr_cleanup(&digest_ctx); return (rc); } rc = digest_mgr_digest_update(sess, &digest_ctx, k_ipad, SHA1_BLOCK_SIZE); if (rc != CKR_OK) { (void) digest_mgr_cleanup(&digest_ctx); return (rc); } rc = digest_mgr_digest_update(sess, &digest_ctx, in_data, in_data_len); if (rc != CKR_OK) { (void) digest_mgr_cleanup(&digest_ctx); return (rc); } hash_len = sizeof (hash); rc = digest_mgr_digest_final(sess, &digest_ctx, hash, &hash_len); if (rc != CKR_OK) { (void) digest_mgr_cleanup(&digest_ctx); return (rc); } (void) digest_mgr_cleanup(&digest_ctx); (void) memset(&digest_ctx, 0x0, sizeof (DIGEST_CONTEXT)); rc = digest_mgr_init(sess, &digest_ctx, &digest_mech); if (rc != CKR_OK) { (void) digest_mgr_cleanup(&digest_ctx); return (rc); } rc = digest_mgr_digest_update(sess, &digest_ctx, k_opad, SHA1_BLOCK_SIZE); if (rc != CKR_OK) { (void) digest_mgr_cleanup(&digest_ctx); return (rc); } rc = digest_mgr_digest_update(sess, &digest_ctx, hash, hash_len); if (rc != CKR_OK) { (void) digest_mgr_cleanup(&digest_ctx); return (rc); } hash_len = sizeof (hash); rc = digest_mgr_digest_final(sess, &digest_ctx, hash, &hash_len); if (rc != CKR_OK) { (void) digest_mgr_cleanup(&digest_ctx); return (rc); } (void) memcpy(out_data, hash, hmac_len); *out_data_len = hmac_len; (void) digest_mgr_cleanup(&digest_ctx); return (CKR_OK); } CK_RV sha1_hmac_verify(SESSION *sess, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *signature, CK_ULONG sig_len) { CK_BYTE hmac[SHA1_DIGEST_LENGTH]; SIGN_VERIFY_CONTEXT hmac_ctx; CK_ULONG hmac_len, len; CK_RV rc; if (! sess || ! ctx || ! in_data || ! signature) { return (CKR_FUNCTION_FAILED); } if (ctx->mech.mechanism == CKM_SHA_1_HMAC_GENERAL) hmac_len = *(CK_ULONG *)ctx->mech.pParameter; else hmac_len = SHA1_DIGEST_LENGTH; (void) memset(&hmac_ctx, 0, sizeof (SIGN_VERIFY_CONTEXT)); rc = sign_mgr_init(sess, &hmac_ctx, &ctx->mech, FALSE, ctx->key); if (rc != CKR_OK) { goto done; } len = sizeof (hmac); rc = sign_mgr_sign(sess, FALSE, &hmac_ctx, in_data, in_data_len, hmac, &len); if (rc != CKR_OK) { goto done; } if ((len != hmac_len) || (len != sig_len)) { rc = CKR_SIGNATURE_LEN_RANGE; goto done; } if (memcmp(hmac, signature, hmac_len) != 0) { rc = CKR_SIGNATURE_INVALID; } done: (void) sign_mgr_cleanup(&hmac_ctx); return (rc); } /* * The Initial Developer of the Original Code is International * Business Machines Corporation. Portions created by IBM * Corporation are Copyright (C) 2005 International Business * Machines Corporation. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the Common Public License as published by * IBM Corporation; either version 1 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * Common Public License for more details. * * You should have received a copy of the Common Public License * along with this program; if not, a copy can be viewed at * http://www.opensource.org/licenses/cpl1.0.php. */ /* (C) COPYRIGHT International Business Machines Corp. 2001, 2002, 2005 */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include "tpmtok_int.h" #include "tpmtok_defs.h" extern pthread_rwlock_t obj_list_rw_mutex; void SC_SetFunctionList(void); struct ST_FCN_LIST function_list; int debugfile = 0; pid_t initedpid = 0; // for initialized pid CK_C_INITIALIZE_ARGS cinit_args = {NULL, NULL, NULL, NULL, 0, NULL}; extern void stlogterm(); extern void stloginit(); extern void stlogit2(int type, char *fmt, ...); extern void stlogit(char *fmt, ...); CK_BBOOL st_Initialized() { return (initedpid == getpid()); } void Fork_Initializer(void) { stlogterm(); stloginit(); // Initialize Logging so we can capture EVERYTHING // Force logout. This cleans out the private session and list // and cleans out the private object map (void) session_mgr_logout_all(); // Clean out the public object map // First parm is no longer used.. (void) object_mgr_purge_map((SESSION *)0xFFFF, PUBLIC); (void) object_mgr_purge_map((SESSION *)0xFFFF, PRIVATE); // This should clear the entire session list out (void) session_mgr_close_all_sessions(); next_session_handle = 1; next_object_handle = 1; while (priv_token_obj_list) { priv_token_obj_list = dlist_remove_node(priv_token_obj_list, priv_token_obj_list); } while (publ_token_obj_list) { publ_token_obj_list = dlist_remove_node(publ_token_obj_list, publ_token_obj_list); } } #define SESSION_HANDLE sSession.sessionh #define SESS_SET \ CK_SESSION_HANDLE hSession = sSession.sessionh; static CK_RV validate_mechanism(CK_MECHANISM_PTR pMechanism) { CK_ULONG i; for (i = 0; i < mech_list_len; i++) { if (pMechanism->mechanism == mech_list[i].mech_type) { return (CKR_OK); } } return (CKR_MECHANISM_INVALID); } #define VALID_MECH(p) \ if (validate_mechanism(p) != CKR_OK) { \ rc = CKR_MECHANISM_INVALID; \ goto done; \ } CK_RV ST_Initialize(void *FunctionList, CK_SLOT_ID SlotNumber, unsigned char *Correlator) { CK_RV rc = CKR_OK; struct ST_FCN_LIST *flist = (struct ST_FCN_LIST *)FunctionList; TSS_HCONTEXT hContext = 0; stlogterm(); stloginit(); if (st_Initialized() == TRUE) { return (CKR_OK); } // assume that the upper API prevents multiple calls of initialize // since that only happens on C_Initialize and that is the // resonsibility of the upper layer.. initialized = FALSE; // check for other completing this before creating mutexes... // make sure that the same process tried to to the init... // thread issues should be caught up above... if (st_Initialized() == TRUE) { goto done; } Fork_Initializer(); (void) pthread_mutex_init(&pkcs_mutex, NULL); (void) pthread_mutex_init(&obj_list_mutex, NULL); (void) pthread_rwlock_init(&obj_list_rw_mutex, NULL); (void) pthread_mutex_init(&sess_list_mutex, NULL); (void) pthread_mutex_init(&login_mutex, NULL); if (st_Initialized() == FALSE) { if ((rc = attach_shm()) != CKR_OK) goto done; nv_token_data = &global_shm->nv_token_data; initialized = TRUE; initedpid = getpid(); SC_SetFunctionList(); if (flist != NULL) (*flist) = function_list; /* Always call the token_specific_init function.... */ rc = token_specific.t_init((char *)Correlator, SlotNumber, &hContext); if (rc != 0) { /* * The token could not be initialized, return OK, but * present no slots. */ rc = CKR_OK; goto done; } else { /* Mark the token as available */ global_shm->token_available = TRUE; } } rc = load_token_data(hContext, nv_token_data); if (rc != CKR_OK) { goto done; } rc = load_public_token_objects(); if (rc != CKR_OK) goto done; (void) XProcLock(xproclock); global_shm->publ_loaded = TRUE; (void) XProcUnLock(xproclock); init_slot_info(nv_token_data); done: if (hContext) Tspi_Context_Close(hContext); return (rc); } /*ARGSUSED*/ CK_RV SC_Finalize(void *argptr) { CK_RV rc; TSS_HCONTEXT hContext; if (st_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } rc = pthread_mutex_lock(&pkcs_mutex); if (rc != CKR_OK) { return (rc); } // // If somebody else has taken care of things, leave... // if (st_Initialized() == FALSE) { (void) pthread_mutex_unlock(&pkcs_mutex); return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (open_tss_context(&hContext)) { (void) pthread_mutex_unlock(&pkcs_mutex); return (CKR_FUNCTION_FAILED); } initialized = FALSE; if (token_specific.t_final != NULL) { token_specific.t_final(hContext); } (void) session_mgr_close_all_sessions(); (void) object_mgr_purge_token_objects(hContext); (void) Tspi_Context_Close(hContext); (void) detach_shm(); rc = pthread_mutex_unlock(&pkcs_mutex); if (rc != CKR_OK) { return (rc); } return (CKR_OK); } /*ARGSUSED*/ CK_RV SC_GetTokenInfo(CK_SLOT_ID sid, CK_TOKEN_INFO_PTR pInfo) { CK_RV rc = CKR_OK; time_t now; if (st_Initialized() == FALSE) return (CKR_CRYPTOKI_NOT_INITIALIZED); if (pInfo == NULL) return (CKR_FUNCTION_FAILED); if (sid != TPM_SLOTID) return (CKR_SLOT_ID_INVALID); (void) memcpy(pInfo, &nv_token_data->token_info, sizeof (CK_TOKEN_INFO)); now = time((time_t *)NULL); (void) strftime((char *)pInfo->utcTime, 16, "%X", localtime(&now)); return (rc); } /*ARGSUSED*/ CK_RV SC_GetMechanismList( CK_SLOT_ID sid, CK_MECHANISM_TYPE_PTR pMechList, CK_ULONG_PTR count) { CK_ULONG i; CK_RV rc = CKR_OK; if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (count == NULL) { rc = CKR_FUNCTION_FAILED; goto done; } if (sid != TPM_SLOTID) { rc = CKR_SLOT_ID_INVALID; goto done; } if (pMechList == NULL) { *count = mech_list_len; rc = CKR_OK; goto done; } if (*count < mech_list_len) { *count = mech_list_len; rc = CKR_BUFFER_TOO_SMALL; goto done; } for (i = 0; i < mech_list_len; i++) pMechList[i] = mech_list[i].mech_type; *count = mech_list_len; rc = CKR_OK; done: if (debugfile) { stlogit2(debugfile, "% - 25s: rc = 0x%08x, # mechanisms: %d\n", "C_GetMechanismList", rc, *count); } return (rc); } /*ARGSUSED*/ CK_RV SC_GetMechanismInfo( CK_SLOT_ID sid, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo) { CK_ULONG i; CK_RV rc = CKR_OK; if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (pInfo == NULL) { rc = CKR_FUNCTION_FAILED; goto done; } if (sid != TPM_SLOTID) { rc = CKR_SLOT_ID_INVALID; goto done; } for (i = 0; i < mech_list_len; i++) { if (mech_list[i].mech_type == type) { (void) memcpy(pInfo, &mech_list[i].mech_info, sizeof (CK_MECHANISM_INFO)); rc = CKR_OK; goto done; } } rc = CKR_MECHANISM_INVALID; done: if (debugfile) { stlogit2(debugfile, "% - 25s: " "rc = 0x%08x, mech type = 0x%08x\n", "C_GetMechanismInfo", rc, type); } return (rc); } /*ARGSUSED*/ CK_RV SC_InitToken( CK_SLOT_ID sid, CK_CHAR_PTR pPin, CK_ULONG ulPinLen, CK_CHAR_PTR pLabel) { CK_RV rc = CKR_OK; CK_BYTE hash_sha[SHA1_DIGEST_LENGTH]; TOKEN_DATA newtoken; TSS_HCONTEXT hContext = 0; if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (sid != TPM_SLOTID) { rc = CKR_SLOT_ID_INVALID; goto done; } if (! pPin || ! pLabel) { rc = CKR_ARGUMENTS_BAD; goto done; } if (open_tss_context(&hContext)) { rc = CKR_FUNCTION_FAILED; goto done; } rc = load_token_data(hContext, &newtoken); if (rc != CKR_OK) { goto done; } if (newtoken.token_info.flags & CKF_SO_PIN_LOCKED) { rc = CKR_PIN_LOCKED; goto done; } rc = token_specific.t_verify_so_pin(hContext, pPin, ulPinLen); if (rc != CKR_OK) { rc = CKR_PIN_INCORRECT; goto done; } /* * Before we reconstruct all the data, we should delete the * token objects from the filesystem. * * Construct a string to delete the token objects. */ (void) object_mgr_destroy_token_objects(hContext); (void) init_token_data(hContext, &newtoken); (void) init_slot_info(&newtoken); /* change the label */ (void) strncpy((char *)newtoken.token_info.label, (char *)pLabel, sizeof (newtoken.token_info.label)); (void) memcpy(newtoken.so_pin_sha, hash_sha, SHA1_DIGEST_LENGTH); newtoken.token_info.flags |= CKF_TOKEN_INITIALIZED; rc = save_token_data(&newtoken); done: if (hContext) (void) Tspi_Context_Close(hContext); return (rc); } CK_RV SC_InitPIN( ST_SESSION_HANDLE sSession, CK_CHAR_PTR pPin, CK_ULONG ulPinLen) { SESSION * sess = NULL; CK_RV rc = CKR_OK; CK_FLAGS * flags = NULL; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (! pPin) { rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_locked(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { rc = CKR_PIN_LOCKED; goto done; } if (sess->session_info.state != CKS_RW_SO_FUNCTIONS) { rc = CKR_USER_NOT_LOGGED_IN; goto done; } rc = token_specific.t_init_pin(sess->hContext, pPin, ulPinLen); if (rc == CKR_OK) { flags = &nv_token_data->token_info.flags; *flags &= ~(CKF_USER_PIN_LOCKED | CKF_USER_PIN_FINAL_TRY | CKF_USER_PIN_COUNT_LOW); rc = save_token_data(nv_token_data); if (rc != CKR_OK) { goto done; } } done: if (debugfile) { stlogit2(debugfile, "% - 25s: session = %08x\n", "C_InitPin", rc, hSession); } return (rc); } CK_RV SC_SetPIN(ST_SESSION_HANDLE sSession, CK_CHAR_PTR pOldPin, CK_ULONG ulOldLen, CK_CHAR_PTR pNewPin, CK_ULONG ulNewLen) { SESSION * sess = NULL; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_locked(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { rc = CKR_PIN_LOCKED; goto done; } rc = token_specific.t_set_pin(sSession, pOldPin, ulOldLen, pNewPin, ulNewLen); done: if (debugfile) { stlogit2(debugfile, "% - 25s: session = %08x\n", "C_SetPin", rc, hSession); } return (rc); } CK_RV SC_OpenSession( CK_SLOT_ID sid, CK_FLAGS flags, CK_SESSION_HANDLE_PTR phSession) { SESSION *sess; CK_RV rc = CKR_OK; TSS_HCONTEXT hContext; if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if ((flags & CKF_RW_SESSION) == 0) { if (session_mgr_so_session_exists()) { return (CKR_SESSION_READ_WRITE_SO_EXISTS); } } if (sid != TPM_SLOTID) { rc = CKR_SLOT_ID_INVALID; goto done; } if (open_tss_context(&hContext)) { rc = CKR_FUNCTION_FAILED; goto done; } rc = pthread_mutex_lock(&pkcs_mutex); if (rc != CKR_OK) { (void) pthread_mutex_unlock(&pkcs_mutex); Tspi_Context_Close(hContext); goto done; } token_specific.t_session(sid); (void) pthread_mutex_unlock(&pkcs_mutex); rc = session_mgr_new(flags, &sess); if (rc != CKR_OK) { Tspi_Context_Close(hContext); goto done; } *phSession = sess->handle; sess->session_info.slotID = sid; /* Open a new context for each session */ sess->hContext = hContext; done: return (rc); } CK_RV SC_CloseSession(ST_SESSION_HANDLE sSession) { SESSION *sess = NULL; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(hSession); if (!sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (token_specific.t_final != NULL) { token_specific.t_final(sess->hContext); } rc = session_mgr_close_session(sess); done: return (rc); } /*ARGSUSED*/ CK_RV SC_CloseAllSessions(CK_SLOT_ID sid) { CK_RV rc = CKR_OK; if (st_Initialized() == FALSE) return (CKR_CRYPTOKI_NOT_INITIALIZED); if (sid != TPM_SLOTID) return (CKR_SLOT_ID_INVALID); rc = session_mgr_close_all_sessions(); return (rc); } CK_RV SC_GetSessionInfo(ST_SESSION_HANDLE sSession, CK_SESSION_INFO_PTR pInfo) { SESSION * sess = NULL; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (! pInfo) { rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } (void) memcpy(pInfo, &sess->session_info, sizeof (CK_SESSION_INFO)); done: return (rc); } CK_RV SC_GetOperationState(ST_SESSION_HANDLE sSession, CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen) { SESSION * sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (! pulOperationStateLen) { rc = CKR_ARGUMENTS_BAD; goto done; } if (! pOperationState) length_only = TRUE; sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } rc = session_mgr_get_op_state(sess, length_only, pOperationState, pulOperationStateLen); done: return (rc); } CK_RV SC_SetOperationState(ST_SESSION_HANDLE sSession, CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen, CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey) { SESSION * sess = NULL; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (!pOperationState || (ulOperationStateLen == 0)) { return (CKR_ARGUMENTS_BAD); } sess = session_mgr_find(hSession); if (! sess) { return (CKR_SESSION_HANDLE_INVALID); } rc = session_mgr_set_op_state(sess, hEncryptionKey, hAuthenticationKey, pOperationState); return (rc); } CK_RV SC_Login(ST_SESSION_HANDLE sSession, CK_USER_TYPE userType, CK_CHAR_PTR pPin, CK_ULONG ulPinLen) { SESSION * sess = NULL; CK_FLAGS * flags = NULL, flagcheck, flagmask; CK_RV rc = CKR_OK; SESS_SET // In v2.11, logins should be exclusive, since token // specific flags may need to be set for a bad login. - KEY rc = pthread_mutex_lock(&login_mutex); if (rc != CKR_OK) { return (CKR_FUNCTION_FAILED); } if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } flags = &nv_token_data->token_info.flags; if (pPin == NULL) { set_login_flags(userType, flags); rc = CKR_ARGUMENTS_BAD; goto done; } if (ulPinLen < MIN_PIN_LEN || ulPinLen > MAX_PIN_LEN) { set_login_flags(userType, flags); rc = CKR_PIN_LEN_RANGE; goto done; } /* * PKCS #11 v2.01 requires that all sessions have the same login status: * --> all sessions are public, all are SO or all are USER */ if (userType == CKU_USER) { if (session_mgr_so_session_exists()) { rc = CKR_USER_ANOTHER_ALREADY_LOGGED_IN; } if (session_mgr_user_session_exists()) { rc = CKR_USER_ALREADY_LOGGED_IN; } } else if (userType == CKU_SO) { if (session_mgr_user_session_exists()) { rc = CKR_USER_ANOTHER_ALREADY_LOGGED_IN; } if (session_mgr_so_session_exists()) { rc = CKR_USER_ALREADY_LOGGED_IN; } if (session_mgr_readonly_exists()) { rc = CKR_SESSION_READ_ONLY_EXISTS; } } else { rc = CKR_USER_TYPE_INVALID; } if (rc != CKR_OK) goto done; if (userType == CKU_USER) { flagcheck = CKF_USER_PIN_LOCKED; flagmask = (CKF_USER_PIN_LOCKED | CKF_USER_PIN_FINAL_TRY | CKF_USER_PIN_COUNT_LOW); } else { flagcheck = CKF_SO_PIN_LOCKED; flagmask = (CKF_SO_PIN_LOCKED | CKF_SO_PIN_FINAL_TRY | CKF_SO_PIN_COUNT_LOW); } if (*flags & flagcheck) { rc = CKR_PIN_LOCKED; goto done; } /* call the pluggable login function here */ rc = token_specific.t_login(sess->hContext, userType, pPin, ulPinLen); if (rc == CKR_OK) { *flags &= ~(flagmask); } else if (rc == CKR_PIN_INCORRECT) { set_login_flags(userType, flags); goto done; } else { goto done; } rc = session_mgr_login_all(userType); done: if (rc == CKR_OK) rc = save_token_data(nv_token_data); (void) pthread_mutex_unlock(&login_mutex); return (rc); } CK_RV SC_Logout(ST_SESSION_HANDLE sSession) { SESSION * sess = NULL; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } // all sessions have the same state so we just have to check one // if (session_mgr_public_session_exists()) { rc = CKR_USER_NOT_LOGGED_IN; goto done; } (void) session_mgr_logout_all(); rc = token_specific.t_logout(sess->hContext); done: return (rc); } CK_RV SC_CreateObject(ST_SESSION_HANDLE sSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject) { SESSION * sess = NULL; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { rc = CKR_PIN_EXPIRED; goto done; } rc = object_mgr_add(sess, pTemplate, ulCount, phObject); done: return (rc); } CK_RV SC_CopyObject( ST_SESSION_HANDLE sSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phNewObject) { SESSION * sess = NULL; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { rc = CKR_PIN_EXPIRED; goto done; } rc = object_mgr_copy(sess, pTemplate, ulCount, hObject, phNewObject); done: return (rc); } CK_RV SC_DestroyObject(ST_SESSION_HANDLE sSession, CK_OBJECT_HANDLE hObject) { SESSION * sess = NULL; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { rc = CKR_PIN_EXPIRED; goto done; } rc = object_mgr_destroy_object(sess, hObject); done: return (rc); } CK_RV SC_GetObjectSize( ST_SESSION_HANDLE sSession, CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize) { SESSION * sess = NULL; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } rc = object_mgr_get_object_size(sess->hContext, hObject, pulSize); done: return (rc); } CK_RV SC_GetAttributeValue(ST_SESSION_HANDLE sSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) { SESSION * sess = NULL; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } rc = object_mgr_get_attribute_values(sess, hObject, pTemplate, ulCount); done: return (rc); } CK_RV SC_SetAttributeValue(ST_SESSION_HANDLE sSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) { SESSION * sess = NULL; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } rc = object_mgr_set_attribute_values(sess, hObject, pTemplate, ulCount); done: return (rc); } CK_RV SC_FindObjectsInit(ST_SESSION_HANDLE sSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) { SESSION * sess = NULL; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { rc = CKR_PIN_EXPIRED; goto done; } if (sess->find_active == TRUE) { rc = CKR_OPERATION_ACTIVE; goto done; } rc = object_mgr_find_init(sess, pTemplate, ulCount); done: return (rc); } CK_RV SC_FindObjects(ST_SESSION_HANDLE sSession, CK_OBJECT_HANDLE_PTR phObject, CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount) { SESSION * sess = NULL; CK_ULONG count = 0; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (! phObject || ! pulObjectCount) { rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->find_active == FALSE) { rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (! sess->find_list) { rc = CKR_FUNCTION_FAILED; goto done; } count = MIN(ulMaxObjectCount, (sess->find_count - sess->find_idx)); (void) memcpy(phObject, sess->find_list + sess->find_idx, count * sizeof (CK_OBJECT_HANDLE)); *pulObjectCount = count; sess->find_idx += count; rc = CKR_OK; done: return (rc); } CK_RV SC_FindObjectsFinal(ST_SESSION_HANDLE sSession) { SESSION * sess = NULL; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->find_active == FALSE) { rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (sess->find_list) free(sess->find_list); sess->find_list = NULL; sess->find_len = 0; sess->find_idx = 0; sess->find_active = FALSE; rc = CKR_OK; done: return (rc); } CK_RV SC_EncryptInit(ST_SESSION_HANDLE sSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { SESSION * sess = NULL; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (! pMechanism) { rc = CKR_ARGUMENTS_BAD; goto done; } VALID_MECH(pMechanism); sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { rc = CKR_PIN_EXPIRED; goto done; } if (sess->encr_ctx.active == TRUE) { rc = CKR_OPERATION_ACTIVE; goto done; } rc = encr_mgr_init(sess, &sess->encr_ctx, OP_ENCRYPT_INIT, pMechanism, hKey); done: return (rc); } CK_RV SC_Encrypt(ST_SESSION_HANDLE sSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen) { SESSION * sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (! pData || ! pulEncryptedDataLen) { rc = CKR_ARGUMENTS_BAD; goto done; } if (sess->encr_ctx.active == FALSE) { rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (! pEncryptedData) length_only = TRUE; rc = encr_mgr_encrypt(sess, length_only, &sess->encr_ctx, pData, ulDataLen, pEncryptedData, pulEncryptedDataLen); done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) (void) encr_mgr_cleanup(&sess->encr_ctx); return (rc); } #if 0 CK_RV SC_EncryptUpdate(ST_SESSION_HANDLE sSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen) { SESSION * sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (! pPart || ! pulEncryptedPartLen) { rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->encr_ctx.active == FALSE) { rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (! pEncryptedPart) length_only = TRUE; rc = encr_mgr_encrypt_update(sess, length_only, &sess->encr_ctx, pPart, ulPartLen, pEncryptedPart, pulEncryptedPartLen); done: if (rc != CKR_OK && rc != CKR_BUFFER_TOO_SMALL) (void) encr_mgr_cleanup(&sess->encr_ctx); return (rc); } CK_RV SC_EncryptFinal(ST_SESSION_HANDLE sSession, CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pulLastEncryptedPartLen) { SESSION * sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (! pulLastEncryptedPartLen) { rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->encr_ctx.active == FALSE) { rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (! pLastEncryptedPart) length_only = TRUE; rc = encr_mgr_encrypt_final(sess, length_only, &sess->encr_ctx, pLastEncryptedPart, pulLastEncryptedPartLen); done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) (void) encr_mgr_cleanup(&sess->encr_ctx); return (rc); } #endif CK_RV SC_DecryptInit(ST_SESSION_HANDLE sSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { SESSION * sess = NULL; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (! pMechanism) { rc = CKR_ARGUMENTS_BAD; goto done; } VALID_MECH(pMechanism); sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { rc = CKR_PIN_EXPIRED; goto done; } if (sess->decr_ctx.active == TRUE) { rc = CKR_OPERATION_ACTIVE; goto done; } rc = decr_mgr_init(sess, &sess->decr_ctx, OP_DECRYPT_INIT, pMechanism, hKey); done: return (rc); } CK_RV SC_Decrypt(ST_SESSION_HANDLE sSession, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) { SESSION * sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (! pEncryptedData || ! pulDataLen) { rc = CKR_ARGUMENTS_BAD; goto done; } if (sess->decr_ctx.active == FALSE) { rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (! pData) length_only = TRUE; rc = decr_mgr_decrypt(sess, length_only, &sess->decr_ctx, pEncryptedData, ulEncryptedDataLen, pData, pulDataLen); done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) (void) decr_mgr_cleanup(&sess->decr_ctx); return (rc); } CK_RV SC_DigestInit(ST_SESSION_HANDLE sSession, CK_MECHANISM_PTR pMechanism) { SESSION * sess = NULL; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (! pMechanism) { rc = CKR_ARGUMENTS_BAD; goto done; } VALID_MECH(pMechanism); sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { rc = CKR_PIN_EXPIRED; goto done; } if (sess->digest_ctx.active == TRUE) { rc = CKR_OPERATION_ACTIVE; goto done; } rc = digest_mgr_init(sess, &sess->digest_ctx, pMechanism); done: return (rc); } CK_RV SC_Digest(ST_SESSION_HANDLE sSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen) { SESSION * sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (! pData || ! pulDigestLen) { rc = CKR_ARGUMENTS_BAD; goto done; } if (sess->digest_ctx.active == FALSE) { rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (! pDigest) length_only = TRUE; rc = digest_mgr_digest(sess, length_only, &sess->digest_ctx, pData, ulDataLen, pDigest, pulDigestLen); done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) (void) digest_mgr_cleanup(&sess->digest_ctx); return (rc); } CK_RV SC_DigestUpdate(ST_SESSION_HANDLE sSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen) { SESSION * sess = NULL; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (! pPart && ulPartLen != 0) { rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->digest_ctx.active == FALSE) { rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (pPart) { rc = digest_mgr_digest_update(sess, &sess->digest_ctx, pPart, ulPartLen); } done: if (rc != CKR_OK) (void) digest_mgr_cleanup(&sess->digest_ctx); return (rc); } CK_RV SC_DigestKey(ST_SESSION_HANDLE sSession, CK_OBJECT_HANDLE hKey) { SESSION * sess = NULL; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->digest_ctx.active == FALSE) { rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } rc = digest_mgr_digest_key(sess, &sess->digest_ctx, hKey); done: if (rc != CKR_OK) (void) digest_mgr_cleanup(&sess->digest_ctx); return (rc); } CK_RV SC_DigestFinal(ST_SESSION_HANDLE sSession, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen) { SESSION * sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (! pulDigestLen) { rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->digest_ctx.active == FALSE) { rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (! pDigest) length_only = TRUE; rc = digest_mgr_digest_final(sess, &sess->digest_ctx, pDigest, pulDigestLen); done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) (void) digest_mgr_cleanup(&sess->digest_ctx); return (rc); } CK_RV SC_SignInit(ST_SESSION_HANDLE sSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { SESSION * sess = NULL; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (! pMechanism) { rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } VALID_MECH(pMechanism); if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { rc = CKR_PIN_EXPIRED; goto done; } if (sess->sign_ctx.active == TRUE) { rc = CKR_OPERATION_ACTIVE; goto done; } rc = sign_mgr_init(sess, &sess->sign_ctx, pMechanism, FALSE, hKey); done: return (rc); } CK_RV SC_Sign(ST_SESSION_HANDLE sSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) { SESSION * sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (!pData || !pulSignatureLen) { rc = CKR_ARGUMENTS_BAD; goto done; } if (sess->sign_ctx.active == FALSE) { rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (! pSignature) length_only = TRUE; rc = sign_mgr_sign(sess, length_only, &sess->sign_ctx, pData, ulDataLen, pSignature, pulSignatureLen); done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) (void) sign_mgr_cleanup(&sess->sign_ctx); return (rc); } CK_RV SC_SignUpdate(ST_SESSION_HANDLE sSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen) { SESSION * sess = NULL; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (! pPart) { rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->sign_ctx.active == FALSE) { rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } rc = sign_mgr_sign_update(sess, &sess->sign_ctx, pPart, ulPartLen); done: if (rc != CKR_OK) (void) sign_mgr_cleanup(&sess->sign_ctx); return (rc); } CK_RV SC_SignFinal(ST_SESSION_HANDLE sSession, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) { SESSION * sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (! pulSignatureLen) { rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->sign_ctx.active == FALSE) { rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (! pSignature) length_only = TRUE; rc = sign_mgr_sign_final(sess, length_only, &sess->sign_ctx, pSignature, pulSignatureLen); done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) (void) sign_mgr_cleanup(&sess->sign_ctx); return (rc); } CK_RV SC_SignRecoverInit(ST_SESSION_HANDLE sSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { SESSION * sess = NULL; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (! pMechanism) { rc = CKR_ARGUMENTS_BAD; goto done; } VALID_MECH(pMechanism); sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { rc = CKR_PIN_EXPIRED; goto done; } if (sess->sign_ctx.active == TRUE) { rc = CKR_OPERATION_ACTIVE; goto done; } rc = sign_mgr_init(sess, &sess->sign_ctx, pMechanism, TRUE, hKey); done: return (rc); } CK_RV SC_SignRecover(ST_SESSION_HANDLE sSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) { SESSION * sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (!pData || !pulSignatureLen) { rc = CKR_ARGUMENTS_BAD; goto done; } if ((sess->sign_ctx.active == FALSE) || (sess->sign_ctx.recover == FALSE)) { rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (! pSignature) length_only = TRUE; rc = sign_mgr_sign_recover(sess, length_only, &sess->sign_ctx, pData, ulDataLen, pSignature, pulSignatureLen); done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) (void) sign_mgr_cleanup(&sess->sign_ctx); return (rc); } CK_RV SC_VerifyInit(ST_SESSION_HANDLE sSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { SESSION * sess = NULL; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (! pMechanism) { rc = CKR_ARGUMENTS_BAD; goto done; } VALID_MECH(pMechanism); sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { rc = CKR_PIN_EXPIRED; goto done; } if (sess->verify_ctx.active == TRUE) { rc = CKR_OPERATION_ACTIVE; goto done; } rc = verify_mgr_init(sess, &sess->verify_ctx, pMechanism, FALSE, hKey); done: return (rc); } CK_RV SC_Verify(ST_SESSION_HANDLE sSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) { SESSION * sess = NULL; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (! pData || ! pSignature) { rc = CKR_ARGUMENTS_BAD; goto done; } if (sess->verify_ctx.active == FALSE) { rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } rc = verify_mgr_verify(sess, &sess->verify_ctx, pData, ulDataLen, pSignature, ulSignatureLen); done: (void) verify_mgr_cleanup(&sess->verify_ctx); return (rc); } CK_RV SC_VerifyUpdate(ST_SESSION_HANDLE sSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen) { SESSION * sess = NULL; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (! pPart) { rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->verify_ctx.active == FALSE) { rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } rc = verify_mgr_verify_update(sess, &sess->verify_ctx, pPart, ulPartLen); done: if (rc != CKR_OK) (void) verify_mgr_cleanup(&sess->verify_ctx); return (rc); } CK_RV SC_VerifyFinal(ST_SESSION_HANDLE sSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) { SESSION * sess = NULL; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (! pSignature) { rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->verify_ctx.active == FALSE) { rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } rc = verify_mgr_verify_final(sess, &sess->verify_ctx, pSignature, ulSignatureLen); done: (void) verify_mgr_cleanup(&sess->verify_ctx); return (rc); } CK_RV SC_VerifyRecoverInit(ST_SESSION_HANDLE sSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { SESSION * sess = NULL; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (! pMechanism) { rc = CKR_ARGUMENTS_BAD; goto done; } VALID_MECH(pMechanism); sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { rc = CKR_PIN_EXPIRED; goto done; } if (sess->verify_ctx.active == TRUE) { rc = CKR_OPERATION_ACTIVE; goto done; } rc = verify_mgr_init(sess, &sess->verify_ctx, pMechanism, TRUE, hKey); done: return (rc); } CK_RV SC_VerifyRecover(ST_SESSION_HANDLE sSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) { SESSION * sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (!pSignature || !pulDataLen) { rc = CKR_ARGUMENTS_BAD; goto done; } if ((sess->verify_ctx.active == FALSE) || (sess->verify_ctx.recover == FALSE)) { rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (! pData) length_only = TRUE; rc = verify_mgr_verify_recover(sess, length_only, &sess->verify_ctx, pSignature, ulSignatureLen, pData, pulDataLen); done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) (void) verify_mgr_cleanup(&sess->verify_ctx); return (rc); } CK_RV SC_GenerateKeyPair(ST_SESSION_HANDLE sSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPublicKey, CK_OBJECT_HANDLE_PTR phPrivateKey) { SESSION * sess = NULL; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (! pMechanism || ! phPublicKey || ! phPrivateKey || (! pPublicKeyTemplate && (ulPublicKeyAttributeCount != 0)) || (! pPrivateKeyTemplate && (ulPrivateKeyAttributeCount != 0))) { rc = CKR_ARGUMENTS_BAD; goto done; } VALID_MECH(pMechanism); sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { rc = CKR_PIN_EXPIRED; goto done; } rc = key_mgr_generate_key_pair(sess, pMechanism, pPublicKeyTemplate, ulPublicKeyAttributeCount, pPrivateKeyTemplate, ulPrivateKeyAttributeCount, phPublicKey, phPrivateKey); done: return (rc); } CK_RV SC_WrapKey(ST_SESSION_HANDLE sSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey, CK_ULONG_PTR pulWrappedKeyLen) { SESSION * sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (! pMechanism || ! pulWrappedKeyLen) { rc = CKR_ARGUMENTS_BAD; goto done; } VALID_MECH(pMechanism); if (! pWrappedKey) length_only = TRUE; sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { rc = CKR_PIN_EXPIRED; goto done; } rc = key_mgr_wrap_key(sess, length_only, pMechanism, hWrappingKey, hKey, pWrappedKey, pulWrappedKeyLen); done: return (rc); } CK_RV SC_UnwrapKey(ST_SESSION_HANDLE sSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey, CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey) { SESSION * sess = NULL; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (! pMechanism || ! pWrappedKey || (! pTemplate && ulCount != 0) || ! phKey) { rc = CKR_ARGUMENTS_BAD; goto done; } VALID_MECH(pMechanism); sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { rc = CKR_PIN_EXPIRED; goto done; } rc = key_mgr_unwrap_key(sess, pMechanism, pTemplate, ulCount, pWrappedKey, ulWrappedKeyLen, hUnwrappingKey, phKey); done: return (rc); } /*ARGSUSED*/ CK_RV SC_SeedRandom(ST_SESSION_HANDLE sSession, CK_BYTE_PTR pSeed, CK_ULONG ulSeedLen) { if (st_Initialized() == FALSE) { return (CKR_CRYPTOKI_NOT_INITIALIZED); } if (pSeed == NULL || ulSeedLen == 0) return (CKR_ARGUMENTS_BAD); return (CKR_OK); } CK_RV SC_GenerateRandom(ST_SESSION_HANDLE sSession, CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen) { SESSION *sess = NULL; CK_RV rc = CKR_OK; SESS_SET if (st_Initialized() == FALSE) { rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (! pRandomData && ulRandomLen != 0) { rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(hSession); if (! sess) { rc = CKR_SESSION_HANDLE_INVALID; goto done; } rc = token_rng(sess->hContext, pRandomData, ulRandomLen); done: return (rc); } void SC_SetFunctionList(void) { function_list.ST_Initialize = ST_Initialize; function_list.ST_Finalize = SC_Finalize; function_list.ST_GetTokenInfo = SC_GetTokenInfo; function_list.ST_GetMechanismList = SC_GetMechanismList; function_list.ST_GetMechanismInfo = SC_GetMechanismInfo; function_list.ST_InitToken = SC_InitToken; function_list.ST_InitPIN = SC_InitPIN; function_list.ST_SetPIN = SC_SetPIN; function_list.ST_OpenSession = SC_OpenSession; function_list.ST_CloseSession = SC_CloseSession; function_list.ST_GetSessionInfo = SC_GetSessionInfo; function_list.ST_GetOperationState = SC_GetOperationState; function_list.ST_SetOperationState = SC_SetOperationState; function_list.ST_Login = SC_Login; function_list.ST_Logout = SC_Logout; function_list.ST_CreateObject = SC_CreateObject; function_list.ST_CopyObject = SC_CopyObject; function_list.ST_DestroyObject = SC_DestroyObject; function_list.ST_GetObjectSize = SC_GetObjectSize; function_list.ST_GetAttributeValue = SC_GetAttributeValue; function_list.ST_SetAttributeValue = SC_SetAttributeValue; function_list.ST_FindObjectsInit = SC_FindObjectsInit; function_list.ST_FindObjects = SC_FindObjects; function_list.ST_FindObjectsFinal = SC_FindObjectsFinal; function_list.ST_EncryptInit = SC_EncryptInit; function_list.ST_Encrypt = SC_Encrypt; function_list.ST_EncryptUpdate = NULL /* SC_EncryptUpdate */; function_list.ST_EncryptFinal = NULL /* SC_EncryptFinal */; function_list.ST_DecryptInit = SC_DecryptInit; function_list.ST_Decrypt = SC_Decrypt; function_list.ST_DecryptUpdate = NULL /* SC_DecryptUpdate */; function_list.ST_DecryptFinal = NULL /* SC_DecryptFinal */; function_list.ST_DigestInit = SC_DigestInit; function_list.ST_Digest = SC_Digest; function_list.ST_DigestUpdate = SC_DigestUpdate; function_list.ST_DigestKey = SC_DigestKey; function_list.ST_DigestFinal = SC_DigestFinal; function_list.ST_SignInit = SC_SignInit; function_list.ST_Sign = SC_Sign; function_list.ST_SignUpdate = SC_SignUpdate; function_list.ST_SignFinal = SC_SignFinal; function_list.ST_SignRecoverInit = SC_SignRecoverInit; function_list.ST_SignRecover = SC_SignRecover; function_list.ST_VerifyInit = SC_VerifyInit; function_list.ST_Verify = SC_Verify; function_list.ST_VerifyUpdate = SC_VerifyUpdate; function_list.ST_VerifyFinal = SC_VerifyFinal; function_list.ST_VerifyRecoverInit = SC_VerifyRecoverInit; function_list.ST_VerifyRecover = SC_VerifyRecover; function_list.ST_DigestEncryptUpdate = NULL; function_list.ST_DecryptDigestUpdate = NULL; function_list.ST_SignEncryptUpdate = NULL; function_list.ST_DecryptVerifyUpdate = NULL; function_list.ST_GenerateKey = NULL; function_list.ST_GenerateKeyPair = SC_GenerateKeyPair; function_list.ST_WrapKey = SC_WrapKey; function_list.ST_UnwrapKey = SC_UnwrapKey; function_list.ST_DeriveKey = NULL; function_list.ST_SeedRandom = SC_SeedRandom; function_list.ST_GenerateRandom = SC_GenerateRandom; function_list.ST_GetFunctionStatus = NULL; function_list.ST_CancelFunction = NULL; } /* * Common Public License Version 0.5 * * THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF * THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, * REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES * RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. * * 1. DEFINITIONS * * "Contribution" means: * a) in the case of the initial Contributor, the * initial code and documentation distributed under * this Agreement, and * * b) in the case of each subsequent Contributor: * i) changes to the Program, and * ii) additions to the Program; * * where such changes and/or additions to the Program * originate from and are distributed by that * particular Contributor. A Contribution 'originates' * from a Contributor if it was added to the Program * by such Contributor itself or anyone acting on such * Contributor's behalf. Contributions do not include * additions to the Program which: (i) are separate * modules of software distributed in conjunction with * the Program under their own license agreement, and * (ii) are not derivative works of the Program. * * * "Contributor" means any person or entity that distributes * the Program. * * "Licensed Patents " mean patent claims licensable by a * Contributor which are necessarily infringed by the use or * sale of its Contribution alone or when combined with the * Program. * * "Program" means the Contributions distributed in * accordance with this Agreement. * * "Recipient" means anyone who receives the Program under * this Agreement, including all Contributors. * * 2. GRANT OF RIGHTS * * a) Subject to the terms of this Agreement, each * Contributor hereby grants Recipient a * no - exclusive, worldwide, royalt - free copyright * license to reproduce, prepare derivative works of, * publicly display, publicly perform, distribute and * sublicense the Contribution of such Contributor, if * any, and such derivative works, in source code and * object code form. * * b) Subject to the terms of this Agreement, each * Contributor hereby grants Recipient a * no - exclusive, worldwide, royalt - free patent * license under Licensed Patents to make, use, sell, * offer to sell, import and otherwise transfer the * Contribution of such Contributor, if any, in source * code and object code form. This patent license * shall apply to the combination of the Contribution * and the Program if, at the time the Contribution is * added by the Contributor, such addition of the * Contribution causes such combination to be covered * by the Licensed Patents. The patent license shall * not apply to any other combinations which include * the Contribution. No hardware per se is licensed * hereunder. * * c) Recipient understands that although each * Contributor grants the licenses to its * Contributions set forth herein, no assurances are * provided by any Contributor that the Program does * not infringe the patent or other intellectual * property rights of any other entity. Each * Contributor disclaims any liability to Recipient * for claims brought by any other entity based on * infringement of intellectual property rights or * otherwise. As a condition to exercising the rights * and licenses granted hereunder, each Recipient * hereby assumes sole responsibility to secure any * other intellectual property rights needed, if any. * * For example, if a third party patent license is * required to allow Recipient to distribute the * Program, it is Recipient's responsibility to * acquire that license before distributing the * Program. * * d) Each Contributor represents that to its * knowledge it has sufficient copyright rights in its * Contribution, if any, to grant the copyright * license set forth in this Agreement. * * 3. REQUIREMENTS * * A Contributor may choose to distribute the Program in * object code form under its own license agreement, provided * that: * a) it complies with the terms and conditions of * this Agreement; and * * b) its license agreement: * i) effectively disclaims on behalf of all * Contributors all warranties and conditions, express * and implied, including warranties or conditions of * title and no - infringement, and implied warranties * or conditions of merchantability and fitness for a * particular purpose; * * ii) effectively excludes on behalf of all * Contributors all liability for damages, including * direct, indirect, special, incidental and * consequential damages, such as lost profits; * * iii) states that any provisions which differ from * this Agreement are offered by that Contributor * alone and not by any other party; and * * iv) states that source code for the Program is * available from such Contributor, and informs * licensees how to obtain it in a reasonable manner * on or through a medium customarily used for * software exchange. * * When the Program is made available in source code form: * a) it must be made available under this Agreement; * and * b) a copy of this Agreement must be included with * each copy of the Program. * * Contributors may not remove or alter any copyright notices * contained within the Program. * * Each Contributor must identify itself as the originator of * its Contribution, if any, in a manner that reasonably * allows subsequent Recipients to identify the originator of * the Contribution. * * * 4. COMMERCIAL DISTRIBUTION * * Commercial distributors of software may accept certain * responsibilities with respect to end users, business * partners and the like. While this license is intended to * facilitate the commercial use of the Program, the * Contributor who includes the Program in a commercial * product offering should do so in a manner which does not * create potential liability for other Contributors. * Therefore, if a Contributor includes the Program in a * commercial product offering, such Contributor ("Commercial * Contributor") hereby agrees to defend and indemnify every * other Contributor ("Indemnified Contributor") against any * losses, damages and costs (collectively "Losses") arising * from claims, lawsuits and other legal actions brought by a * third party against the Indemnified Contributor to the * extent caused by the acts or omissions of such Commercial * Contributor in connection with its distribution of the * Program in a commercial product offering. The obligations * in this section do not apply to any claims or Losses * relating to any actual or alleged intellectual property * infringement. In order to qualify, an Indemnified * Contributor must: a) promptly notify the Commercial * Contributor in writing of such claim, and b) allow the * Commercial Contributor to control, and cooperate with the * Commercial Contributor in, the defense and any related * settlement negotiations. The Indemnified Contributor may * participate in any such claim at its own expense. * * * For example, a Contributor might include the Program in a * commercial product offering, Product X. That Contributor * is then a Commercial Contributor. If that Commercial * Contributor then makes performance claims, or offers * warranties related to Product X, those performance claims * and warranties are such Commercial Contributor's * responsibility alone. Under this section, the Commercial * Contributor would have to defend claims against the other * Contributors related to those performance claims and * warranties, and if a court requires any other Contributor * to pay any damages as a result, the Commercial Contributor * must pay those damages. * * * 5. NO WARRANTY * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE * PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR * IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR * CONDITIONS OF TITLE, NO - INFRINGEMENT, MERCHANTABILITY OR * FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely * responsible for determining the appropriateness of using * and distributing the Program and assumes all risks * associated with its exercise of rights under this * Agreement, including but not limited to the risks and * costs of program errors, compliance with applicable laws, * damage to or loss of data, programs or equipment, and * unavailability or interruption of operations. * * 6. DISCLAIMER OF LIABILITY * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER * RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION * LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE * OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * 7. GENERAL * * If any provision of this Agreement is invalid or * unenforceable under applicable law, it shall not affect * the validity or enforceability of the remainder of the * terms of this Agreement, and without further action by the * parties hereto, such provision shall be reformed to the * minimum extent necessary to make such provision valid and * enforceable. * * * If Recipient institutes patent litigation against a * Contributor with respect to a patent applicable to * software (including a cros - claim or counterclaim in a * lawsuit), then any patent licenses granted by that * Contributor to such Recipient under this Agreement shall * terminate as of the date such litigation is filed. In * addition, If Recipient institutes patent litigation * against any entity (including a cros - claim or * counterclaim in a lawsuit) alleging that the Program * itself (excluding combinations of the Program with other * software or hardware) infringes such Recipient's * patent(s), then such Recipient's rights granted under * Section 2(b) shall terminate as of the date such * litigation is filed. * * All Recipient's rights under this Agreement shall * terminate if it fails to comply with any of the material * terms or conditions of this Agreement and does not cure * such failure in a reasonable period of time after becoming * aware of such noncompliance. If all Recipient's rights * under this Agreement terminate, Recipient agrees to cease * use and distribution of the Program as soon as reasonably * practicable. However, Recipient's obligations under this * Agreement and any licenses granted by Recipient relating * to the Program shall continue and survive. * * Everyone is permitted to copy and distribute copies of * this Agreement, but in order to avoid inconsistency the * Agreement is copyrighted and may only be modified in the * following manner. The Agreement Steward reserves the right * to publish new versions (including revisions) of this * Agreement from time to time. No one other than the * Agreement Steward has the right to modify this Agreement. * * IBM is the initial Agreement Steward. IBM may assign the * responsibility to serve as the Agreement Steward to a * suitable separate entity. Each new version of the * Agreement will be given a distinguishing version number. * The Program (including Contributions) may always be * distributed subject to the version of the Agreement under * which it was received. In addition, after a new version of * the Agreement is published, Contributor may elect to * distribute the Program (including its Contributions) under * the new version. Except as expressly stated in Sections * 2(a) and 2(b) above, Recipient receives no rights or * licenses to the intellectual property of any Contributor * under this Agreement, whether expressly, by implication, * estoppel or otherwise. All rights in the Program not * expressly granted under this Agreement are reserved. * * * This Agreement is governed by the laws of the State of New * York and the intellectual property laws of the United * States of America. No party to this Agreement will bring a * legal action under this Agreement more than one year after * the cause of action arose. Each party waives its rights to * a jury trial in any resulting litigation. * * * * (C) COPYRIGHT International Business Machines Corp. 2001, 2002 */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include "tpmtok_int.h" pthread_rwlock_t obj_list_rw_mutex = PTHREAD_RWLOCK_INITIALIZER; static CK_RV object_mgr_search_shm_for_obj(TOK_OBJ_ENTRY *, CK_ULONG, CK_ULONG, OBJECT *, CK_ULONG *); static CK_RV object_mgr_update_from_shm(TSS_HCONTEXT); static CK_RV object_mgr_check_shm(TSS_HCONTEXT, OBJECT *); static CK_RV check_object_access(SESSION *sess, OBJECT *o) { CK_BBOOL sess_obj, priv_obj; CK_RV rc = CKR_OK; /* * check whether session has permissions to create the object, etc * * Object R/O R/W R/O R/W R/W * Type Public Public User User SO * ------------------------------------------------------------- * Public session R/W R/W R/W R/W R/W * Private session R/W R/W * Public token R/O R/W R/O R/W R/W * Private token R/O R/W */ sess_obj = object_is_session_object(o); priv_obj = object_is_private(o); if (sess->session_info.state == CKS_RO_PUBLIC_SESSION) { if (priv_obj) { rc = CKR_USER_NOT_LOGGED_IN; goto done; } if (!sess_obj) { rc = CKR_SESSION_READ_ONLY; goto done; } } if (sess->session_info.state == CKS_RO_USER_FUNCTIONS) { if (! sess_obj) { rc = CKR_SESSION_READ_ONLY; goto done; } } if (sess->session_info.state == CKS_RW_PUBLIC_SESSION) { if (priv_obj) { rc = CKR_USER_NOT_LOGGED_IN; goto done; } } if (sess->session_info.state == CKS_RW_SO_FUNCTIONS) { if (priv_obj) { rc = CKR_USER_NOT_LOGGED_IN; goto done; } } done: return (rc); } CK_RV object_mgr_add(SESSION * sess, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE * handle) { OBJECT * o = NULL; CK_BBOOL priv_obj, sess_obj; CK_RV rc; if (! sess || ! pTemplate || ! handle) { return (CKR_FUNCTION_FAILED); } rc = pthread_mutex_lock(&obj_list_mutex); if (rc != CKR_OK) return (CKR_FUNCTION_FAILED); rc = object_create(pTemplate, ulCount, &o); if (rc != CKR_OK) { goto done; } rc = check_object_access(sess, o); if (rc != CKR_OK) goto done; /* * okay, object is created and the session permissions look okay. * add the object to the appropriate list and assign an object handle */ sess_obj = object_is_session_object(o); priv_obj = object_is_private(o); if (sess_obj) { o->session = sess; (void) memset(o->name, 0x00, sizeof (CK_BYTE) * 8); sess_obj_list = dlist_add_as_first(sess_obj_list, o); } else { CK_BYTE current[8]; CK_BYTE next[8]; rc = XProcLock(xproclock); if (rc != CKR_OK) { goto done; } else { if (priv_obj) { if (global_shm->num_priv_tok_obj >= MAX_TOK_OBJS) { rc = CKR_HOST_MEMORY; (void) XProcUnLock(xproclock); goto done; } } else { if (global_shm->num_publ_tok_obj >= MAX_TOK_OBJS) { rc = CKR_HOST_MEMORY; (void) XProcUnLock(xproclock); goto done; } } (void) memcpy(current, &nv_token_data->next_token_object_name, 8); o->session = NULL; (void) memcpy(&o->name, current, 8); (void) compute_next_token_obj_name(current, next); (void) memcpy(&nv_token_data->next_token_object_name, next, 8); rc = save_token_object(sess->hContext, o); if (rc != CKR_OK) { (void) XProcUnLock(xproclock); goto done; } (void) object_mgr_add_to_shm(o); (void) XProcUnLock(xproclock); (void) save_token_data(nv_token_data); } if (priv_obj) priv_token_obj_list = dlist_add_as_last(priv_token_obj_list, o); else publ_token_obj_list = dlist_add_as_last(publ_token_obj_list, o); } rc = object_mgr_add_to_map(sess, o, handle); if (rc != CKR_OK) { DL_NODE *node = NULL; if (sess_obj) { node = dlist_find(sess_obj_list, o); if (node) sess_obj_list = dlist_remove_node(sess_obj_list, node); } else { (void) delete_token_object(o); if (priv_obj) { node = dlist_find(priv_token_obj_list, o); if (node) priv_token_obj_list = dlist_remove_node( priv_token_obj_list, node); } else { node = dlist_find(publ_token_obj_list, o); if (node) publ_token_obj_list = dlist_remove_node( publ_token_obj_list, node); } rc = XProcLock(xproclock); if (rc != CKR_OK) { goto done; } (void) object_mgr_del_from_shm(o); (void) XProcUnLock(xproclock); } } done: (void) pthread_mutex_unlock(&obj_list_mutex); if ((rc != CKR_OK) && (o != NULL)) (void) object_free(o); return (rc); } CK_RV object_mgr_add_to_map(SESSION * sess, OBJECT * obj, CK_OBJECT_HANDLE * handle) { OBJECT_MAP *map_node = NULL; if (! sess || ! obj || ! handle) { return (CKR_FUNCTION_FAILED); } map_node = (OBJECT_MAP *)malloc(sizeof (OBJECT_MAP)); if (! map_node) { return (CKR_HOST_MEMORY); } map_node->handle = next_object_handle++; map_node->session = sess; map_node->ptr = obj; if (obj->session != NULL) map_node->is_session_obj = TRUE; else map_node->is_session_obj = FALSE; // add the new map entry to the list if (pthread_rwlock_wrlock(&obj_list_rw_mutex)) { return (CKR_FUNCTION_FAILED); } object_map = dlist_add_as_first(object_map, map_node); (void) pthread_rwlock_unlock(&obj_list_rw_mutex); *handle = map_node->handle; return (CKR_OK); } // object_mgr_copy() // // algorithm: // 1) find the old object // 2) get the template from the old object // 3) merge in the new object's template // 4) perform class - specific sanity checks // CK_RV object_mgr_copy(SESSION * sess, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE old_handle, CK_OBJECT_HANDLE * new_handle) { OBJECT *old_obj = NULL; OBJECT *new_obj = NULL; CK_BBOOL priv_obj; CK_BBOOL sess_obj; CK_RV rc; if (! sess || ! pTemplate || ! new_handle) { return (CKR_FUNCTION_FAILED); } rc = pthread_mutex_lock(&obj_list_mutex); if (rc != CKR_OK) return (CKR_FUNCTION_FAILED); rc = object_mgr_find_in_map1(sess->hContext, old_handle, &old_obj); if (rc != CKR_OK) { goto done; } rc = object_copy(pTemplate, ulCount, old_obj, &new_obj); if (rc != CKR_OK) { goto done; } rc = check_object_access(sess, new_obj); if (rc != CKR_OK) goto done; sess_obj = object_is_session_object(new_obj); priv_obj = object_is_private(new_obj); if (sess_obj) { new_obj->session = sess; (void) memset(&new_obj->name, 0x00, sizeof (CK_BYTE) * 8); sess_obj_list = dlist_add_as_first(sess_obj_list, new_obj); } else { CK_BYTE current[8]; CK_BYTE next[8]; rc = XProcLock(xproclock); if (rc != CKR_OK) { goto done; } else { if (priv_obj) { if (global_shm->num_priv_tok_obj >= MAX_TOK_OBJS) { (void) XProcUnLock(xproclock); rc = CKR_HOST_MEMORY; goto done; } } else { if (global_shm->num_publ_tok_obj >= MAX_TOK_OBJS) { (void) XProcUnLock(xproclock); rc = CKR_HOST_MEMORY; goto done; } } (void) memcpy(current, &nv_token_data->next_token_object_name, 8); new_obj->session = NULL; (void) memcpy(&new_obj->name, current, 8); (void) compute_next_token_obj_name(current, next); (void) memcpy(&nv_token_data->next_token_object_name, next, 8); rc = save_token_object(sess->hContext, new_obj); if (rc != CKR_OK) { (void) XProcUnLock(xproclock); goto done; } (void) object_mgr_add_to_shm(new_obj); (void) XProcUnLock(xproclock); (void) save_token_data(nv_token_data); } if (priv_obj) priv_token_obj_list = dlist_add_as_last( priv_token_obj_list, new_obj); else publ_token_obj_list = dlist_add_as_last( publ_token_obj_list, new_obj); } rc = object_mgr_add_to_map(sess, new_obj, new_handle); if (rc != CKR_OK) { DL_NODE *node = NULL; if (sess_obj) { node = dlist_find(sess_obj_list, new_obj); if (node) sess_obj_list = dlist_remove_node( sess_obj_list, node); } else { (void) delete_token_object(new_obj); if (priv_obj) { node = dlist_find(priv_token_obj_list, new_obj); if (node) priv_token_obj_list = dlist_remove_node( priv_token_obj_list, node); } else { node = dlist_find(publ_token_obj_list, new_obj); if (node) publ_token_obj_list = dlist_remove_node( publ_token_obj_list, node); } rc = XProcLock(xproclock); if (rc != CKR_OK) { goto done; } (void) object_mgr_del_from_shm(new_obj); (void) XProcUnLock(xproclock); } } done: (void) pthread_mutex_unlock(&obj_list_mutex); if ((rc != CKR_OK) && (new_obj != NULL)) (void) object_free(new_obj); return (rc); } // // determines whether the session is allowed to create an object. creates // the object but doesn't add the object to any object lists or to the // process' object map. // CK_RV object_mgr_create_skel(SESSION * sess, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount, CK_ULONG mode, CK_ULONG obj_type, CK_ULONG sub_class, OBJECT ** obj) { OBJECT *o = NULL; CK_RV rc; CK_BBOOL priv_obj; CK_BBOOL sess_obj; if (! sess || ! obj) { return (CKR_FUNCTION_FAILED); } if (! pTemplate && (ulCount != 0)) { return (CKR_FUNCTION_FAILED); } rc = object_create_skel(pTemplate, ulCount, mode, obj_type, sub_class, &o); if (rc != CKR_OK) { return (rc); } sess_obj = object_is_session_object(o); priv_obj = object_is_private(o); if (sess->session_info.state == CKS_RO_PUBLIC_SESSION) { if (priv_obj) { (void) object_free(o); return (CKR_USER_NOT_LOGGED_IN); } if (! sess_obj) { (void) object_free(o); return (CKR_SESSION_READ_ONLY); } } if (sess->session_info.state == CKS_RO_USER_FUNCTIONS) { if (! sess_obj) { (void) object_free(o); return (CKR_SESSION_READ_ONLY); } } if (sess->session_info.state == CKS_RW_PUBLIC_SESSION) { if (priv_obj) { (void) object_free(o); return (CKR_USER_NOT_LOGGED_IN); } } if (sess->session_info.state == CKS_RW_SO_FUNCTIONS) { if (priv_obj) { (void) object_free(o); return (CKR_USER_NOT_LOGGED_IN); } } *obj = o; return (CKR_OK); } CK_RV object_mgr_create_final(SESSION * sess, OBJECT * obj, CK_OBJECT_HANDLE * handle) { CK_BBOOL sess_obj; CK_BBOOL priv_obj; CK_RV rc; if (!sess || !obj || !handle) return (CKR_FUNCTION_FAILED); rc = pthread_mutex_lock(&obj_list_mutex); if (rc != CKR_OK) return (CKR_FUNCTION_FAILED); sess_obj = object_is_session_object(obj); priv_obj = object_is_private(obj); if (sess_obj) { obj->session = sess; (void) memset(obj->name, 0x0, sizeof (CK_BYTE) * 8); sess_obj_list = dlist_add_as_first(sess_obj_list, obj); } else { CK_BYTE current[8]; CK_BYTE next[8]; rc = XProcLock(xproclock); if (rc != CKR_OK) { goto done; } else { if (priv_obj) { if (global_shm->num_priv_tok_obj >= MAX_TOK_OBJS) { (void) XProcUnLock(xproclock); rc = CKR_HOST_MEMORY; goto done; } } else { if (global_shm->num_publ_tok_obj >= MAX_TOK_OBJS) { (void) XProcUnLock(xproclock); rc = CKR_HOST_MEMORY; goto done; } } (void) memcpy(current, &nv_token_data->next_token_object_name, 8); obj->session = NULL; (void) memcpy(&obj->name, current, 8); (void) compute_next_token_obj_name(current, next); (void) memcpy(&nv_token_data->next_token_object_name, next, 8); rc = save_token_object(sess->hContext, obj); if (rc != CKR_OK) { (void) XProcUnLock(xproclock); goto done; } (void) object_mgr_add_to_shm(obj); (void) XProcUnLock(xproclock); (void) save_token_data(nv_token_data); } if (priv_obj) priv_token_obj_list = dlist_add_as_last( priv_token_obj_list, obj); else publ_token_obj_list = dlist_add_as_last( publ_token_obj_list, obj); } rc = object_mgr_add_to_map(sess, obj, handle); if (rc != CKR_OK) { DL_NODE *node = NULL; if (sess_obj) { node = dlist_find(sess_obj_list, obj); if (node) sess_obj_list = dlist_remove_node( sess_obj_list, node); } else { (void) delete_token_object(obj); if (priv_obj) { node = dlist_find(priv_token_obj_list, obj); if (node) priv_token_obj_list = dlist_remove_node( priv_token_obj_list, node); } else { node = dlist_find(publ_token_obj_list, obj); if (node) publ_token_obj_list = dlist_remove_node( publ_token_obj_list, node); } rc = XProcLock(xproclock); if (rc != CKR_OK) { goto done; } (void) object_mgr_del_from_shm(obj); (void) XProcUnLock(xproclock); } } done: (void) pthread_mutex_unlock(&obj_list_mutex); return (rc); } CK_RV object_mgr_destroy_object(SESSION * sess, CK_OBJECT_HANDLE handle) { OBJECT * obj = NULL; CK_BBOOL sess_obj; CK_BBOOL priv_obj; CK_RV rc; if (! sess) return (CKR_FUNCTION_FAILED); rc = pthread_mutex_lock(&obj_list_mutex); if (rc != CKR_OK) return (CKR_FUNCTION_FAILED); rc = object_mgr_find_in_map1(sess->hContext, handle, &obj); if (rc != CKR_OK) { goto done; } rc = check_object_access(sess, obj); if (rc != CKR_OK) goto done; sess_obj = object_is_session_object(obj); priv_obj = object_is_private(obj); if (sess_obj) { DL_NODE *node; node = dlist_find(sess_obj_list, obj); if (node) { (void) object_mgr_remove_from_map(handle); (void) object_free(obj); sess_obj_list = dlist_remove_node( sess_obj_list, node); rc = CKR_OK; goto done; } } else { DL_NODE *node = NULL; (void) delete_token_object(obj); if (priv_obj) node = dlist_find(priv_token_obj_list, obj); else node = dlist_find(publ_token_obj_list, obj); if (node) { rc = XProcLock(xproclock); if (rc != CKR_OK) { goto done; } (void) object_mgr_del_from_shm(obj); (void) XProcUnLock(xproclock); (void) object_mgr_remove_from_map(handle); (void) object_free(obj); if (priv_obj) priv_token_obj_list = dlist_remove_node( priv_token_obj_list, node); else publ_token_obj_list = dlist_remove_node( publ_token_obj_list, node); rc = CKR_OK; goto done; } } rc = CKR_FUNCTION_FAILED; done: (void) pthread_mutex_unlock(&obj_list_mutex); return (rc); } CK_RV object_mgr_destroy_token_objects(TSS_HCONTEXT hContext) { CK_BBOOL locked2 = FALSE; CK_RV rc; rc = pthread_mutex_lock(&obj_list_mutex); if (rc != CKR_OK) return (CKR_FUNCTION_FAILED); while (publ_token_obj_list) { OBJECT *obj = (OBJECT *)publ_token_obj_list->data; CK_OBJECT_HANDLE handle; rc = object_mgr_find_in_map2(hContext, obj, &handle); if (rc == CKR_OK) { (void) object_mgr_remove_from_map(handle); } (void) delete_token_object(obj); (void) object_free(obj); publ_token_obj_list = dlist_remove_node( publ_token_obj_list, publ_token_obj_list); } while (priv_token_obj_list) { OBJECT *obj = (OBJECT *)priv_token_obj_list->data; CK_OBJECT_HANDLE handle; rc = object_mgr_find_in_map2(hContext, obj, &handle); if (rc == CKR_OK) { (void) object_mgr_remove_from_map(handle); } (void) delete_token_object(obj); (void) object_free(obj); priv_token_obj_list = dlist_remove_node( priv_token_obj_list, priv_token_obj_list); } // now we want to purge the token object list in shared memory // rc = XProcLock(xproclock); if (rc == CKR_OK) { locked2 = TRUE; global_shm->num_priv_tok_obj = 0; global_shm->num_publ_tok_obj = 0; (void) memset(&global_shm->publ_tok_objs, 0x0, MAX_TOK_OBJS * sizeof (TOK_OBJ_ENTRY)); (void) memset(&global_shm->priv_tok_objs, 0x0, MAX_TOK_OBJS * sizeof (TOK_OBJ_ENTRY)); } (void) pthread_mutex_unlock(&obj_list_mutex); if (locked2 == TRUE) (void) XProcUnLock(xproclock); return (rc); } // // Locates the specified object in the map // without going and checking for cache update // CK_RV object_mgr_find_in_map_nocache(CK_OBJECT_HANDLE handle, OBJECT ** ptr) { DL_NODE * node = NULL; OBJECT * obj = NULL; if (! ptr) { return (CKR_FUNCTION_FAILED); } if (pthread_rwlock_rdlock(&obj_list_rw_mutex)) { return (CKR_FUNCTION_FAILED); } node = object_map; while (node) { OBJECT_MAP *map = (OBJECT_MAP *)node->data; if (map->handle == handle) { obj = map->ptr; break; } node = node->next; } (void) pthread_rwlock_unlock(&obj_list_rw_mutex); if (obj == NULL || node == NULL) { return (CKR_OBJECT_HANDLE_INVALID); } if (object_is_session_object(obj) == TRUE) { *ptr = obj; return (CKR_OK); } *ptr = obj; return (CKR_OK); } CK_RV object_mgr_find_in_map1( TSS_HCONTEXT hContext, CK_OBJECT_HANDLE handle, OBJECT ** ptr) { DL_NODE * node = NULL; OBJECT * obj = NULL; if (! ptr) { return (CKR_FUNCTION_FAILED); } if (pthread_rwlock_rdlock(&obj_list_rw_mutex)) { return (CKR_FUNCTION_FAILED); } node = object_map; while (node) { OBJECT_MAP *map = (OBJECT_MAP *)node->data; if (map->handle == handle) { obj = map->ptr; break; } node = node->next; } (void) pthread_rwlock_unlock(&obj_list_rw_mutex); if (obj == NULL || node == NULL) { return (CKR_OBJECT_HANDLE_INVALID); } if (object_is_session_object(obj) == TRUE) { *ptr = obj; return (CKR_OK); } (void) object_mgr_check_shm(hContext, obj); *ptr = obj; return (CKR_OK); } CK_RV object_mgr_find_in_map2( TSS_HCONTEXT hContext, OBJECT * obj, CK_OBJECT_HANDLE * handle) { DL_NODE * node = NULL; CK_OBJECT_HANDLE h = (CK_OBJECT_HANDLE)NULL; if (! obj || ! handle) { return (CKR_FUNCTION_FAILED); } if (pthread_rwlock_rdlock(&obj_list_rw_mutex)) { return (CKR_FUNCTION_FAILED); } node = object_map; while (node) { OBJECT_MAP *map = (OBJECT_MAP *)node->data; if (map->ptr == obj) { h = map->handle; break; } node = node->next; } (void) pthread_rwlock_unlock(&obj_list_rw_mutex); if (node == NULL) { return (CKR_OBJECT_HANDLE_INVALID); } if (object_is_session_object(obj) == TRUE) { *handle = h; return (CKR_OK); } (void) object_mgr_check_shm(hContext, obj); *handle = h; return (CKR_OK); } CK_RV object_mgr_find_init(SESSION * sess, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount) { if (! sess) { return (CKR_FUNCTION_FAILED); } if (sess->find_active != FALSE) { return (CKR_OPERATION_ACTIVE); } // initialize the found object list. if it doesn't exist, allocate // a list big enough for 10 handles. we'll reallocate if we need more // if (sess->find_list != NULL) { (void) memset(sess->find_list, 0x0, sess->find_len * sizeof (CK_OBJECT_HANDLE)); } else { sess->find_list = (CK_OBJECT_HANDLE *)malloc( 10 * sizeof (CK_OBJECT_HANDLE)); if (! sess->find_list) { return (CKR_HOST_MEMORY); } else { (void) memset(sess->find_list, 0x0, 10 * sizeof (CK_OBJECT_HANDLE)); sess->find_len = 10; } } sess->find_count = 0; sess->find_idx = 0; // --- need to grab the object lock here if (pthread_mutex_lock(&obj_list_mutex)) return (CKR_FUNCTION_FAILED); (void) object_mgr_update_from_shm(sess->hContext); // which objects can be return (ed: // // Public Session: public session objects, public token objects // User Session: all session objects, all token objects // SO session: public session objects, public token objects // switch (sess->session_info.state) { case CKS_RO_PUBLIC_SESSION: case CKS_RW_PUBLIC_SESSION: case CKS_RW_SO_FUNCTIONS: (void) object_mgr_find_build_list(sess, pTemplate, ulCount, publ_token_obj_list, TRUE); (void) object_mgr_find_build_list(sess, pTemplate, ulCount, sess_obj_list, TRUE); break; case CKS_RO_USER_FUNCTIONS: case CKS_RW_USER_FUNCTIONS: (void) object_mgr_find_build_list(sess, pTemplate, ulCount, priv_token_obj_list, FALSE); (void) object_mgr_find_build_list(sess, pTemplate, ulCount, publ_token_obj_list, FALSE); (void) object_mgr_find_build_list(sess, pTemplate, ulCount, sess_obj_list, FALSE); break; } (void) pthread_mutex_unlock(&obj_list_mutex); sess->find_active = TRUE; return (CKR_OK); } CK_RV object_mgr_find_build_list(SESSION * sess, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount, DL_NODE * obj_list, CK_BBOOL public_only) { OBJECT * obj = NULL; DL_NODE * node = NULL; CK_OBJECT_HANDLE handle; CK_BBOOL is_priv; CK_BBOOL match; CK_BBOOL hw_feature = FALSE; CK_BBOOL hidden_object = FALSE; CK_RV rc; CK_ATTRIBUTE * attr; unsigned int i; if (! sess) { return (CKR_FUNCTION_FAILED); } if (! obj_list) return (CKR_OK); // PKCS#11 v2.11 (pg. 79): "When searching using C_FindObjectsInit // and C_FindObjects, hardware feature objects are not returned // unless the CKA_CLASS attribute in the template has the value // CKO_HW_FEATURE." So, we check for CKO_HW_FEATURE and if its set, // we'll find these objects below. - KEY for (i = 0; i < ulCount; i++) { if (pTemplate[i].type == CKA_CLASS) { if (*(CK_ULONG *)pTemplate[i].pValue == CKO_HW_FEATURE) { hw_feature = TRUE; break; } } if (pTemplate[i].type == CKA_HIDDEN) { if (*(CK_BBOOL *)pTemplate[i].pValue == TRUE) { hidden_object = TRUE; break; } } } node = obj_list; while (node) { match = FALSE; obj = (OBJECT *)node->data; is_priv = object_is_private(obj); if ((is_priv == FALSE) || (public_only == FALSE)) { if (pTemplate == NULL || ulCount == 0) match = TRUE; else match = template_compare(pTemplate, ulCount, obj->template); } if (match) { rc = object_mgr_find_in_map2(sess->hContext, obj, &handle); if (rc != CKR_OK) { rc = object_mgr_add_to_map(sess, obj, &handle); if (rc != CKR_OK) { return (CKR_FUNCTION_FAILED); } } if (rc == CKR_OK) { if ((hw_feature == FALSE) && (template_attribute_find(obj->template, CKA_CLASS, &attr) == TRUE)) { if (*(CK_OBJECT_CLASS *)attr->pValue == CKO_HW_FEATURE) goto next_loop; } if ((hidden_object == FALSE) && (template_attribute_find(obj->template, CKA_HIDDEN, &attr) == TRUE)) { if (*(CK_BBOOL *)attr->pValue == TRUE) goto next_loop; } sess->find_list[ sess->find_count ] = handle; sess->find_count++; if (sess->find_count >= sess->find_len) { sess->find_len += 15; sess->find_list = (CK_OBJECT_HANDLE *)realloc( sess->find_list, sess->find_len * sizeof (CK_OBJECT_HANDLE)); if (! sess->find_list) { return (CKR_HOST_MEMORY); } } } } next_loop: node = node->next; } return (CKR_OK); } CK_RV object_mgr_find_final(SESSION *sess) { if (! sess) { return (CKR_FUNCTION_FAILED); } if (sess->find_active == FALSE) { return (CKR_OPERATION_NOT_INITIALIZED); } free(sess->find_list); sess->find_list = NULL; sess->find_count = 0; sess->find_idx = 0; sess->find_active = FALSE; return (CKR_OK); } CK_RV object_mgr_get_attribute_values(SESSION * sess, CK_OBJECT_HANDLE handle, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount) { OBJECT * obj; CK_BBOOL priv_obj; CK_RV rc; if (! pTemplate) { return (CKR_FUNCTION_FAILED); } rc = pthread_mutex_lock(&obj_list_mutex); if (rc != CKR_OK) return (CKR_FUNCTION_FAILED); rc = object_mgr_find_in_map1(sess->hContext, handle, &obj); if (rc != CKR_OK) { goto done; } priv_obj = object_is_private(obj); if (priv_obj == TRUE) { if (sess->session_info.state == CKS_RO_PUBLIC_SESSION || sess->session_info.state == CKS_RW_PUBLIC_SESSION) { rc = CKR_USER_NOT_LOGGED_IN; goto done; } } rc = object_get_attribute_values(obj, pTemplate, ulCount); done: (void) pthread_mutex_unlock(&obj_list_mutex); return (rc); } CK_RV object_mgr_get_object_size( TSS_HCONTEXT hContext, CK_OBJECT_HANDLE handle, CK_ULONG * size) { OBJECT * obj; CK_RV rc; rc = pthread_mutex_lock(&obj_list_mutex); if (rc != CKR_OK) return (CKR_FUNCTION_FAILED); rc = object_mgr_find_in_map1(hContext, handle, &obj); if (rc != CKR_OK) { rc = CKR_OBJECT_HANDLE_INVALID; goto done; } *size = object_get_size(obj); done: (void) pthread_mutex_unlock(&obj_list_mutex); return (rc); } // object_mgr_invalidate_handle1() // // Returns: TRUE if successfully removes the node // FALSE if cannot remove the node (not found, etc) // CK_BBOOL object_mgr_invalidate_handle1(CK_OBJECT_HANDLE handle) { DL_NODE *node = NULL; if (pthread_rwlock_wrlock(&obj_list_rw_mutex)) { return (CKR_FUNCTION_FAILED); } node = object_map; while (node) { OBJECT_MAP *map = (OBJECT_MAP *)node->data; if (map->handle == handle) { object_map = dlist_remove_node(object_map, node); free(map); (void) pthread_rwlock_unlock(&obj_list_rw_mutex); return (TRUE); } node = node->next; } (void) pthread_rwlock_unlock(&obj_list_rw_mutex); return (FALSE); } // object_mgr_invalidate_handle2() // // Returns: TRUE if successfully removes the node // FALSE if cannot remove the node (not found, etc) // CK_BBOOL object_mgr_invalidate_handle2(OBJECT *obj) { DL_NODE *node = NULL; if (! obj) return (FALSE); if (pthread_rwlock_wrlock(&obj_list_rw_mutex)) { return (CKR_FUNCTION_FAILED); } node = object_map; while (node) { OBJECT_MAP *map = (OBJECT_MAP *)node->data; if (map->ptr == obj) { object_map = dlist_remove_node(object_map, node); free(map); (void) pthread_rwlock_unlock(&obj_list_rw_mutex); return (TRUE); } node = node->next; } (void) pthread_rwlock_unlock(&obj_list_rw_mutex); return (FALSE); } // object_mgr_purge_session_objects() // // Args: SESSION * // SESS_OBJ_TYPE: can be ALL, PRIVATE or PUBLIC // // Remove all session objects owned by the specified session satisfying // the 'type' requirements // CK_BBOOL object_mgr_purge_session_objects(SESSION * sess, SESS_OBJ_TYPE type) { DL_NODE *node = NULL; DL_NODE *next = NULL; OBJECT *obj = NULL; CK_BBOOL del; CK_RV rc; if (!sess) return (FALSE); rc = pthread_mutex_lock(&obj_list_mutex); if (rc != CKR_OK) return (FALSE); node = sess_obj_list; while (node) { obj = (OBJECT *)node->data; del = FALSE; if (obj->session == sess) { if (type == PRIVATE) { if (object_is_private(obj)) del = TRUE; } else if (type == PUBLIC) { if (object_is_public(obj)) del = TRUE; } else if (type == ALL) del = TRUE; } if (del == TRUE) { CK_OBJECT_HANDLE handle; CK_RV rc; rc = object_mgr_find_in_map2(sess->hContext, obj, &handle); if (rc == CKR_OK) { (void) object_mgr_invalidate_handle1(handle); (void) object_free(obj); } next = node->next; sess_obj_list = dlist_remove_node(sess_obj_list, node); node = next; } else node = node->next; } (void) pthread_mutex_unlock(&obj_list_mutex); return (TRUE); } // // This routine cleans up the list of token objects. in general, we don't // need to do this but when tracing memory leaks, it's best that we free // everything that we've allocated. // CK_BBOOL object_mgr_purge_token_objects(TSS_HCONTEXT hContext) { DL_NODE *node = NULL; DL_NODE *next = NULL; OBJECT *obj = NULL; CK_RV rc; rc = pthread_mutex_lock(&obj_list_mutex); if (rc != CKR_OK) return (FALSE); node = publ_token_obj_list; while (publ_token_obj_list) { CK_OBJECT_HANDLE handle; CK_RV rc; obj = (OBJECT *)node->data; rc = object_mgr_find_in_map2(hContext, obj, &handle); if (rc == CKR_OK) { (void) object_mgr_invalidate_handle1(handle); } (void) object_free(obj); next = node->next; publ_token_obj_list = dlist_remove_node( publ_token_obj_list, node); node = next; } node = priv_token_obj_list; while (priv_token_obj_list) { CK_OBJECT_HANDLE handle; CK_RV rc; obj = (OBJECT *)node->data; rc = object_mgr_find_in_map2(hContext, obj, &handle); if (rc == CKR_OK) (void) object_mgr_invalidate_handle1(handle); (void) object_free(obj); next = node->next; priv_token_obj_list = dlist_remove_node( priv_token_obj_list, node); node = next; } (void) pthread_mutex_unlock(&obj_list_mutex); return (TRUE); } CK_BBOOL object_mgr_purge_private_token_objects(TSS_HCONTEXT hContext) { OBJECT * obj = NULL; DL_NODE * node = NULL; DL_NODE * next = NULL; CK_RV rc; rc = pthread_mutex_lock(&obj_list_mutex); if (rc != CKR_OK) return (FALSE); node = priv_token_obj_list; while (priv_token_obj_list) { CK_OBJECT_HANDLE handle; CK_RV rc; obj = (OBJECT *)node->data; rc = object_mgr_find_in_map2(hContext, obj, &handle); if (rc == CKR_OK) { (void) object_mgr_invalidate_handle1(handle); } (void) object_free(obj); next = node->next; priv_token_obj_list = dlist_remove_node( priv_token_obj_list, node); node = next; } (void) pthread_mutex_unlock(&obj_list_mutex); return (TRUE); } CK_RV object_mgr_remove_from_map(CK_OBJECT_HANDLE handle) { DL_NODE *node = NULL; if (pthread_rwlock_wrlock(&obj_list_rw_mutex)) { return (CKR_FUNCTION_FAILED); } node = object_map; while (node) { OBJECT_MAP *map = (OBJECT_MAP *)node->data; if (map->handle == handle) { object_map = dlist_remove_node(object_map, node); free(map); (void) pthread_rwlock_unlock(&obj_list_rw_mutex); return (CKR_OK); } node = node->next; } (void) pthread_rwlock_unlock(&obj_list_rw_mutex); return (CKR_FUNCTION_FAILED); } CK_RV object_mgr_restore_obj(CK_BYTE *data, OBJECT *oldObj) { OBJECT * obj = NULL; CK_BBOOL priv; CK_RV rc; if (! data) { return (CKR_FUNCTION_FAILED); } if (oldObj != NULL) { obj = oldObj; rc = object_restore(data, &obj, TRUE); } else { rc = object_restore(data, &obj, FALSE); if (rc == CKR_OK) { priv = object_is_private(obj); if (priv) priv_token_obj_list = dlist_add_as_last( priv_token_obj_list, obj); else publ_token_obj_list = dlist_add_as_last( publ_token_obj_list, obj); (void) XProcLock(xproclock); if (priv) { if (global_shm->priv_loaded == FALSE) { if (global_shm->num_priv_tok_obj < MAX_TOK_OBJS) (void) object_mgr_add_to_shm( obj); else rc = CKR_HOST_MEMORY; } } else { if (global_shm->publ_loaded == FALSE) { if (global_shm->num_publ_tok_obj < MAX_TOK_OBJS) (void) object_mgr_add_to_shm( obj); else rc = CKR_HOST_MEMORY; } } (void) XProcUnLock(xproclock); } } // make the callers have to have the mutes // to many grab it now. return (rc); } CK_RV object_mgr_set_attribute_values(SESSION * sess, CK_OBJECT_HANDLE handle, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount) { OBJECT * obj; CK_BBOOL sess_obj, priv_obj; CK_BBOOL modifiable; CK_RV rc; if (! pTemplate) { return (CKR_FUNCTION_FAILED); } rc = pthread_mutex_lock(&obj_list_mutex); if (rc != CKR_OK) return (CKR_FUNCTION_FAILED); rc = object_mgr_find_in_map1(sess->hContext, handle, &obj); if (rc != CKR_OK) { (void) pthread_mutex_unlock(&obj_list_mutex); return (CKR_OBJECT_HANDLE_INVALID); } (void) pthread_mutex_unlock(&obj_list_mutex); modifiable = object_is_modifiable(obj); sess_obj = object_is_session_object(obj); priv_obj = object_is_private(obj); if (! modifiable) { return (CKR_ATTRIBUTE_READ_ONLY); } rc = check_object_access(sess, obj); if (rc != CKR_OK) return (rc); rc = object_set_attribute_values(obj, pTemplate, ulCount); if (rc != CKR_OK) { return (rc); } if (! sess_obj) { TOK_OBJ_ENTRY *entry = NULL; CK_ULONG index; obj->count_lo++; if (obj->count_lo == 0) obj->count_hi++; rc = save_token_object(sess->hContext, obj); if (rc != CKR_OK) return (rc); rc = XProcLock(xproclock); if (rc != CKR_OK) { return (rc); } if (priv_obj) { rc = object_mgr_search_shm_for_obj( global_shm->priv_tok_objs, 0, global_shm->num_priv_tok_obj - 1, obj, &index); if (rc != CKR_OK) { (void) XProcUnLock(xproclock); return (rc); } entry = &global_shm->priv_tok_objs[index]; } else { rc = object_mgr_search_shm_for_obj( global_shm->publ_tok_objs, 0, global_shm->num_publ_tok_obj - 1, obj, &index); if (rc != CKR_OK) { (void) XProcUnLock(xproclock); return (rc); } entry = &global_shm->publ_tok_objs[index]; } entry->count_lo = obj->count_lo; entry->count_hi = obj->count_hi; (void) XProcUnLock(xproclock); } return (rc); } CK_RV object_mgr_add_to_shm(OBJECT *obj) { TOK_OBJ_ENTRY * entry = NULL; CK_BBOOL priv; priv = object_is_private(obj); if (priv) entry = &global_shm->priv_tok_objs[ global_shm->num_priv_tok_obj]; else entry = &global_shm->publ_tok_objs[ global_shm->num_publ_tok_obj]; entry->deleted = FALSE; entry->count_lo = 0; entry->count_hi = 0; (void) memcpy(entry->name, obj->name, 8); if (priv) { global_shm->num_priv_tok_obj++; } else { global_shm->num_publ_tok_obj++; } return (CKR_OK); } CK_RV object_mgr_del_from_shm(OBJECT *obj) { CK_ULONG index, count; CK_BBOOL priv; CK_RV rc; priv = object_is_private(obj); if (priv) { rc = object_mgr_search_shm_for_obj(global_shm->priv_tok_objs, 0, global_shm->num_priv_tok_obj - 1, obj, &index); if (rc != CKR_OK) { return (CKR_FUNCTION_FAILED); } global_shm->num_priv_tok_obj--; if (index > global_shm->num_priv_tok_obj) { count = index - global_shm->num_priv_tok_obj; } else { count = global_shm->num_priv_tok_obj - index; } if (count > 0) { (void) memcpy((char *)&global_shm->priv_tok_objs[index], (char *)&global_shm->priv_tok_objs[index + 1], sizeof (TOK_OBJ_ENTRY) * count); (void) memset((char *)&global_shm->priv_tok_objs[ global_shm->num_priv_tok_obj + 1], 0, sizeof (TOK_OBJ_ENTRY)); } else { (void) memset((char *)&global_shm->priv_tok_objs[ global_shm->num_priv_tok_obj], 0, sizeof (TOK_OBJ_ENTRY)); } } else { rc = object_mgr_search_shm_for_obj(global_shm->publ_tok_objs, 0, global_shm->num_publ_tok_obj - 1, obj, &index); if (rc != CKR_OK) { return (CKR_FUNCTION_FAILED); } global_shm->num_publ_tok_obj--; if (index > global_shm->num_publ_tok_obj) { count = index - global_shm->num_publ_tok_obj; } else { count = global_shm->num_publ_tok_obj - index; } if (count > 0) { (void) memcpy((char *)&global_shm->publ_tok_objs[index], (char *)&global_shm->publ_tok_objs[index + 1], sizeof (TOK_OBJ_ENTRY) * count); (void) memset((char *)&global_shm->publ_tok_objs[ global_shm->num_publ_tok_obj + 1], 0, sizeof (TOK_OBJ_ENTRY)); } else { (void) memset((char *)&global_shm->publ_tok_objs[ global_shm->num_publ_tok_obj], 0, sizeof (TOK_OBJ_ENTRY)); } } return (CKR_OK); } static CK_RV object_mgr_check_shm(TSS_HCONTEXT hContext, OBJECT *obj) { TOK_OBJ_ENTRY * entry = NULL; CK_BBOOL priv; CK_ULONG index; CK_RV rc; priv = object_is_private(obj); if (priv) { rc = object_mgr_search_shm_for_obj( global_shm->priv_tok_objs, 0, global_shm->num_priv_tok_obj - 1, obj, &index); if (rc != CKR_OK) { return (CKR_FUNCTION_FAILED); } entry = &global_shm->priv_tok_objs[index]; } else { rc = object_mgr_search_shm_for_obj( global_shm->publ_tok_objs, 0, global_shm->num_publ_tok_obj - 1, obj, &index); if (rc != CKR_OK) { return (CKR_FUNCTION_FAILED); } entry = &global_shm->publ_tok_objs[index]; } if ((obj->count_hi == entry->count_hi) && (obj->count_lo == entry->count_lo)) return (CKR_OK); rc = reload_token_object(hContext, obj); return (rc); } /*ARGSUSED*/ static CK_RV object_mgr_search_shm_for_obj( TOK_OBJ_ENTRY *obj_list, CK_ULONG lo, CK_ULONG hi, OBJECT *obj, CK_ULONG *index) { CK_ULONG idx; if (obj->index == 0) { for (idx = lo; idx <= hi; idx++) { if (memcmp(obj->name, obj_list[idx].name, 8) == 0) { *index = idx; obj->index = idx; return (CKR_OK); } } } else { if (memcmp(obj->name, obj_list[obj->index].name, 8) == 0) { *index = obj->index; return (CKR_OK); } else { for (idx = lo; idx <= hi; idx++) { if (memcmp(obj->name, obj_list[idx].name, 8) == 0) { *index = idx; obj->index = idx; return (CKR_OK); } } } } return (CKR_FUNCTION_FAILED); } static CK_RV object_mgr_update_publ_tok_obj_from_shm(TSS_HCONTEXT hContext) { DL_NODE * node = NULL; DL_NODE * next = NULL; TOK_OBJ_ENTRY * te = NULL; OBJECT * obj = NULL; CK_OBJECT_HANDLE handle; CK_ULONG index; int val; CK_RV rc; node = publ_token_obj_list; index = 0; while ((node != NULL) && (index < global_shm->num_publ_tok_obj)) { te = &global_shm->publ_tok_objs[index]; obj = (OBJECT *)node->data; val = memcmp(obj->name, te->name, 8); // 3 cases: // 1) object in local list but not in the global list, // need to remove from local list // 2) object in both lists, need to compare counters // and update as needed // 3) object in global list but not in the local list, // need to add the object here. // if (val < 0) { rc = object_mgr_find_in_map2(hContext, obj, &handle); if (rc == CKR_OK) { (void) object_mgr_remove_from_map(handle); } (void) object_free(obj); next = node->next; publ_token_obj_list = dlist_remove_node( publ_token_obj_list, node); } else if (val == 0) { if ((te->count_hi != obj->count_hi) || (te->count_lo != obj->count_lo)) { (void) reload_token_object(hContext, obj); obj->count_hi = te->count_hi; obj->count_lo = te->count_lo; } next = node->next; index++; } else { DL_NODE *new_node = NULL; OBJECT *new_obj = NULL; new_obj = (OBJECT *)malloc(sizeof (OBJECT)); (void) memset(new_obj, 0x0, sizeof (OBJECT)); (void) memcpy(new_obj->name, te->name, 8); (void) reload_token_object(hContext, new_obj); new_node = (DL_NODE *)malloc(sizeof (DL_NODE)); new_node->data = new_obj; new_node->next = node->next; node->next = new_node; new_node->prev = node; next = new_node->next; index++; } node = next; } if ((node == NULL) && (index < global_shm->num_publ_tok_obj)) { OBJECT *new_obj = NULL; unsigned int i; for (i = index; i < global_shm->num_publ_tok_obj; i++) { new_obj = (OBJECT *)malloc(sizeof (OBJECT)); (void) memset(new_obj, 0x0, sizeof (OBJECT)); te = &global_shm->publ_tok_objs[index]; (void) memcpy(new_obj->name, te->name, 8); (void) reload_token_object(hContext, new_obj); publ_token_obj_list = dlist_add_as_last( publ_token_obj_list, new_obj); } } else if ((node != NULL) && (index >= global_shm->num_publ_tok_obj)) { while (node) { obj = (OBJECT *)node->data; rc = object_mgr_find_in_map2(hContext, obj, &handle); if (rc == CKR_OK) { (void) object_mgr_remove_from_map(handle); } (void) object_free(obj); next = node->next; publ_token_obj_list = dlist_remove_node( publ_token_obj_list, node); node = next; } } return (CKR_OK); } static CK_RV object_mgr_update_priv_tok_obj_from_shm(TSS_HCONTEXT hContext) { DL_NODE * node = NULL; DL_NODE * next = NULL; TOK_OBJ_ENTRY * te = NULL; OBJECT * obj = NULL; CK_OBJECT_HANDLE handle; CK_ULONG index; int val; CK_RV rc; node = priv_token_obj_list; index = 0; if (! (global_login_state == CKS_RW_USER_FUNCTIONS || global_login_state == CKS_RO_USER_FUNCTIONS)) { return (CKR_OK); } while ((node != NULL) && (index < global_shm->num_priv_tok_obj)) { te = &global_shm->priv_tok_objs[index]; obj = (OBJECT *)node->data; val = memcmp(obj->name, te->name, 8); if (val < 0) { rc = object_mgr_find_in_map2(hContext, obj, &handle); if (rc == CKR_OK) { (void) object_mgr_remove_from_map(handle); } (void) object_free(obj); next = node->next; priv_token_obj_list = dlist_remove_node( priv_token_obj_list, node); } else if (val == 0) { if ((te->count_hi != obj->count_hi) || (te->count_lo != obj->count_lo)) { (void) reload_token_object(hContext, obj); obj->count_hi = te->count_hi; obj->count_lo = te->count_lo; } next = node->next; index++; } else { DL_NODE *new_node = NULL; OBJECT *new_obj = NULL; new_obj = (OBJECT *)malloc(sizeof (OBJECT)); (void) memset(new_obj, 0x0, sizeof (OBJECT)); (void) memcpy(new_obj->name, te->name, 8); (void) reload_token_object(hContext, new_obj); new_node = (DL_NODE *)malloc(sizeof (DL_NODE)); new_node->data = new_obj; new_node->next = node->next; node->next = new_node; new_node->prev = node; next = new_node->next; index++; } node = next; } if ((node == NULL) && (index < global_shm->num_priv_tok_obj)) { OBJECT *new_obj = NULL; unsigned int i; for (i = index; i < global_shm->num_priv_tok_obj; i++) { new_obj = (OBJECT *)malloc(sizeof (OBJECT)); (void) memset(new_obj, 0x0, sizeof (OBJECT)); te = &global_shm->priv_tok_objs[index]; (void) memcpy(new_obj->name, te->name, 8); (void) reload_token_object(hContext, new_obj); priv_token_obj_list = dlist_add_as_last( priv_token_obj_list, new_obj); } } else if ((node != NULL) && (index >= global_shm->num_priv_tok_obj)) { while (node) { obj = (OBJECT *)node->data; rc = object_mgr_find_in_map2(hContext, obj, &handle); if (rc == CKR_OK) { (void) object_mgr_remove_from_map(handle); } (void) object_free(obj); next = node->next; priv_token_obj_list = dlist_remove_node( priv_token_obj_list, node); node = next; } } return (CKR_OK); } static CK_RV object_mgr_update_from_shm(TSS_HCONTEXT hContext) { (void) object_mgr_update_publ_tok_obj_from_shm(hContext); (void) object_mgr_update_priv_tok_obj_from_shm(hContext); return (CKR_OK); } /*ARGSUSED*/ CK_BBOOL object_mgr_purge_map( SESSION *sess, SESS_OBJ_TYPE type) { DL_NODE *node = NULL; DL_NODE *next = NULL; if (pthread_rwlock_wrlock(&obj_list_rw_mutex)) { return (CKR_FUNCTION_FAILED); } node = object_map; while (node) { OBJECT_MAP *map = (OBJECT_MAP *)node->data; OBJECT *obj = (OBJECT *)map->ptr; next = node->next; if (type == PRIVATE) { if (object_is_private(obj)) { object_map = dlist_remove_node( object_map, node); free(map); } } if (type == PUBLIC) { if (object_is_public(obj)) { object_map = dlist_remove_node( object_map, node); free(map); } } node = next; } (void) pthread_rwlock_unlock(&obj_list_rw_mutex); return (TRUE); } /* * Common Public License Version 0.5 * * THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF * THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, * REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES * RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. * * 1. DEFINITIONS * * "Contribution" means: * a) in the case of the initial Contributor, the * initial code and documentation distributed under * this Agreement, and * * b) in the case of each subsequent Contributor: * i) changes to the Program, and * ii) additions to the Program; * * where such changes and/or additions to the Program * originate from and are distributed by that * particular Contributor. A Contribution 'originates' * from a Contributor if it was added to the Program * by such Contributor itself or anyone acting on such * Contributor's behalf. Contributions do not include * additions to the Program which: (i) are separate * modules of software distributed in conjunction with * the Program under their own license agreement, and * (ii) are not derivative works of the Program. * * * "Contributor" means any person or entity that distributes * the Program. * * "Licensed Patents " mean patent claims licensable by a * Contributor which are necessarily infringed by the use or * sale of its Contribution alone or when combined with the * Program. * * "Program" means the Contributions distributed in * accordance with this Agreement. * * "Recipient" means anyone who receives the Program under * this Agreement, including all Contributors. * * 2. GRANT OF RIGHTS * * a) Subject to the terms of this Agreement, each * Contributor hereby grants Recipient a * no - exclusive, worldwide, royalt - free copyright * license to reproduce, prepare derivative works of, * publicly display, publicly perform, distribute and * sublicense the Contribution of such Contributor, if * any, and such derivative works, in source code and * object code form. * * b) Subject to the terms of this Agreement, each * Contributor hereby grants Recipient a * no - exclusive, worldwide, royalt - free patent * license under Licensed Patents to make, use, sell, * offer to sell, import and otherwise transfer the * Contribution of such Contributor, if any, in source * code and object code form. This patent license * shall apply to the combination of the Contribution * and the Program if, at the time the Contribution is * added by the Contributor, such addition of the * Contribution causes such combination to be covered * by the Licensed Patents. The patent license shall * not apply to any other combinations which include * the Contribution. No hardware per se is licensed * hereunder. * * c) Recipient understands that although each * Contributor grants the licenses to its * Contributions set forth herein, no assurances are * provided by any Contributor that the Program does * not infringe the patent or other intellectual * property rights of any other entity. Each * Contributor disclaims any liability to Recipient * for claims brought by any other entity based on * infringement of intellectual property rights or * otherwise. As a condition to exercising the rights * and licenses granted hereunder, each Recipient * hereby assumes sole responsibility to secure any * other intellectual property rights needed, if any. * * For example, if a third party patent license is * required to allow Recipient to distribute the * Program, it is Recipient's responsibility to * acquire that license before distributing the * Program. * * d) Each Contributor represents that to its * knowledge it has sufficient copyright rights in its * Contribution, if any, to grant the copyright * license set forth in this Agreement. * * 3. REQUIREMENTS * * A Contributor may choose to distribute the Program in * object code form under its own license agreement, provided * that: * a) it complies with the terms and conditions of * this Agreement; and * * b) its license agreement: * i) effectively disclaims on behalf of all * Contributors all warranties and conditions, express * and implied, including warranties or conditions of * title and no - infringement, and implied warranties * or conditions of merchantability and fitness for a * particular purpose; * * ii) effectively excludes on behalf of all * Contributors all liability for damages, including * direct, indirect, special, incidental and * consequential damages, such as lost profits; * * iii) states that any provisions which differ from * this Agreement are offered by that Contributor * alone and not by any other party; and * * iv) states that source code for the Program is * available from such Contributor, and informs * licensees how to obtain it in a reasonable manner * on or through a medium customarily used for * software exchange. * * When the Program is made available in source code form: * a) it must be made available under this Agreement; * and * b) a copy of this Agreement must be included with * each copy of the Program. * * Contributors may not remove or alter any copyright notices * contained within the Program. * * Each Contributor must identify itself as the originator of * its Contribution, if any, in a manner that reasonably * allows subsequent Recipients to identify the originator of * the Contribution. * * * 4. COMMERCIAL DISTRIBUTION * * Commercial distributors of software may accept certain * responsibilities with respect to end users, business * partners and the like. While this license is intended to * facilitate the commercial use of the Program, the * Contributor who includes the Program in a commercial * product offering should do so in a manner which does not * create potential liability for other Contributors. * Therefore, if a Contributor includes the Program in a * commercial product offering, such Contributor ("Commercial * Contributor") hereby agrees to defend and indemnify every * other Contributor ("Indemnified Contributor") against any * losses, damages and costs (collectively "Losses") arising * from claims, lawsuits and other legal actions brought by a * third party against the Indemnified Contributor to the * extent caused by the acts or omissions of such Commercial * Contributor in connection with its distribution of the * Program in a commercial product offering. The obligations * in this section do not apply to any claims or Losses * relating to any actual or alleged intellectual property * infringement. In order to qualify, an Indemnified * Contributor must: a) promptly notify the Commercial * Contributor in writing of such claim, and b) allow the * Commercial Contributor to control, and cooperate with the * Commercial Contributor in, the defense and any related * settlement negotiations. The Indemnified Contributor may * participate in any such claim at its own expense. * * * For example, a Contributor might include the Program in a * commercial product offering, Product X. That Contributor * is then a Commercial Contributor. If that Commercial * Contributor then makes performance claims, or offers * warranties related to Product X, those performance claims * and warranties are such Commercial Contributor's * responsibility alone. Under this section, the Commercial * Contributor would have to defend claims against the other * Contributors related to those performance claims and * warranties, and if a court requires any other Contributor * to pay any damages as a result, the Commercial Contributor * must pay those damages. * * * 5. NO WARRANTY * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE * PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR * IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR * CONDITIONS OF TITLE, NO - INFRINGEMENT, MERCHANTABILITY OR * FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely * responsible for determining the appropriateness of using * and distributing the Program and assumes all risks * associated with its exercise of rights under this * Agreement, including but not limited to the risks and * costs of program errors, compliance with applicable laws, * damage to or loss of data, programs or equipment, and * unavailability or interruption of operations. * * 6. DISCLAIMER OF LIABILITY * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER * RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION * LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE * OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * 7. GENERAL * * If any provision of this Agreement is invalid or * unenforceable under applicable law, it shall not affect * the validity or enforceability of the remainder of the * terms of this Agreement, and without further action by the * parties hereto, such provision shall be reformed to the * minimum extent necessary to make such provision valid and * enforceable. * * * If Recipient institutes patent litigation against a * Contributor with respect to a patent applicable to * software (including a cros - claim or counterclaim in a * lawsuit), then any patent licenses granted by that * Contributor to such Recipient under this Agreement shall * terminate as of the date such litigation is filed. In * addition, If Recipient institutes patent litigation * against any entity (including a cros - claim or * counterclaim in a lawsuit) alleging that the Program * itself (excluding combinations of the Program with other * software or hardware) infringes such Recipient's * patent(s), then such Recipient's rights granted under * Section 2(b) shall terminate as of the date such * litigation is filed. * * All Recipient's rights under this Agreement shall * terminate if it fails to comply with any of the material * terms or conditions of this Agreement and does not cure * such failure in a reasonable period of time after becoming * aware of such noncompliance. If all Recipient's rights * under this Agreement terminate, Recipient agrees to cease * use and distribution of the Program as soon as reasonably * practicable. However, Recipient's obligations under this * Agreement and any licenses granted by Recipient relating * to the Program shall continue and survive. * * Everyone is permitted to copy and distribute copies of * this Agreement, but in order to avoid inconsistency the * Agreement is copyrighted and may only be modified in the * following manner. The Agreement Steward reserves the right * to publish new versions (including revisions) of this * Agreement from time to time. No one other than the * Agreement Steward has the right to modify this Agreement. * * IBM is the initial Agreement Steward. IBM may assign the * responsibility to serve as the Agreement Steward to a * suitable separate entity. Each new version of the * Agreement will be given a distinguishing version number. * The Program (including Contributions) may always be * distributed subject to the version of the Agreement under * which it was received. In addition, after a new version of * the Agreement is published, Contributor may elect to * distribute the Program (including its Contributions) under * the new version. Except as expressly stated in Sections * 2(a) and 2(b) above, Recipient receives no rights or * licenses to the intellectual property of any Contributor * under this Agreement, whether expressly, by implication, * estoppel or otherwise. All rights in the Program not * expressly granted under this Agreement are reserved. * * * This Agreement is governed by the laws of the State of New * York and the intellectual property laws of the United * States of America. No party to this Agreement will bring a * legal action under this Agreement more than one year after * the cause of action arose. Each party waives its rights to * a jury trial in any resulting litigation. * * * * (C) COPYRIGHT International Business Machines Corp. 2001, 2002 */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include "tpmtok_int.h" // object_create() // // Creates an object with the specified attributes. Verifies that all required // attributes are present and adds any missing attributes that have Cryptoki // defined default values. This routine does not check whether the session is // authorized to create the object. That is done elsewhere // (see object_mgr_create()) CK_RV object_create(CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount, OBJECT ** obj) { OBJECT * o = NULL; CK_ATTRIBUTE * attr = NULL; CK_ATTRIBUTE * sensitive = NULL; CK_ATTRIBUTE * extractable = NULL; CK_ATTRIBUTE * local = NULL; CK_BBOOL class_given = FALSE; CK_BBOOL subclass_given = FALSE; CK_BBOOL flag; CK_ULONG class = 0xFFFFFFFF, subclass = 0xFFFFFFFF; CK_RV rc; unsigned int i; if (! pTemplate) { return (CKR_FUNCTION_FAILED); } // extract the object class and subclass // attr = pTemplate; for (i = 0; i < ulCount; i++, attr++) { if (attr->type == CKA_CLASS) { class = *(CK_OBJECT_CLASS *)attr->pValue; class_given = TRUE; } if (attr->type == CKA_CERTIFICATE_TYPE) { subclass = *(CK_CERTIFICATE_TYPE *)attr->pValue; subclass_given = TRUE; } if (attr->type == CKA_KEY_TYPE) { subclass = *(CK_KEY_TYPE *)attr->pValue; subclass_given = TRUE; } if (attr->type == CKA_HW_FEATURE_TYPE) { subclass = *(CK_HW_FEATURE_TYPE *)attr->pValue; subclass_given = TRUE; } } if (class_given == FALSE) { return (CKR_TEMPLATE_INCOMPLETE); } if (class != CKO_DATA && subclass_given != TRUE) { return (CKR_TEMPLATE_INCOMPLETE); } rc = object_create_skel(pTemplate, ulCount, MODE_CREATE, class, subclass, &o); if (rc != CKR_OK) { return (rc); } // for key objects, we need be careful... // // note: I would think that keys loaded with C_CreateObject should // have their CKA_NEVER_EXTRACTABLE == FALSE and // CKA_ALWAYS_SENSITIVE == FALSE since the key data was presumably // stored in the clear prior to the call to C_CreateObject. The // PKCS #11 spec doesn't impose this restriction however. // if (class == CKO_PRIVATE_KEY || class == CKO_SECRET_KEY) { rc = template_attribute_find(o->template, CKA_SENSITIVE, &attr); if (rc == FALSE) { rc = CKR_FUNCTION_FAILED; goto error; } flag = *(CK_BBOOL *)attr->pValue; rc = build_attribute(CKA_ALWAYS_SENSITIVE, &flag, sizeof (CK_BYTE), &sensitive); if (rc != CKR_OK) { goto error; } rc = template_attribute_find(o->template, CKA_EXTRACTABLE, &attr); if (rc == FALSE) { rc = CKR_FUNCTION_FAILED; goto error; } flag = *(CK_BBOOL *)attr->pValue; flag = (~flag) & 0x1; rc = build_attribute(CKA_NEVER_EXTRACTABLE, &flag, sizeof (CK_BYTE), &extractable); if (rc != CKR_OK) { goto error; } (void) template_update_attribute(o->template, sensitive); (void) template_update_attribute(o->template, extractable); } *obj = o; return (CKR_OK); error: if (sensitive) free(sensitive); if (extractable) free(extractable); if (local) free(local); (void) object_free(o); return (rc); } // object_copy() // // Builds a copy of the specified object. The new object gets the original // object's attribute template plus any additional attributes that are // specified. Verifies that all required attributes are present. This // routine does not check whether the session is authorized to copy the // object -- routines at the individual object level don't have the // concept of "session". These checks are done by the object manager. // CK_RV object_copy(CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount, OBJECT * old_obj, OBJECT ** new_obj) { TEMPLATE * tmpl = NULL; TEMPLATE * new_tmpl = NULL; OBJECT * o = NULL; CK_BBOOL found; CK_ULONG class, subclass; CK_RV rc; if (! old_obj || ! pTemplate || ! new_obj) { return (CKR_FUNCTION_FAILED); } o = (OBJECT *)malloc(sizeof (OBJECT)); tmpl = (TEMPLATE *)malloc(sizeof (TEMPLATE)); new_tmpl = (TEMPLATE *)malloc(sizeof (TEMPLATE)); if (! o || ! tmpl || ! new_tmpl) { rc = CKR_HOST_MEMORY; goto error; } (void) memset(o, 0x0, sizeof (OBJECT)); (void) memset(tmpl, 0x0, sizeof (TEMPLATE)); (void) memset(new_tmpl, 0x0, sizeof (TEMPLATE)); // copy the original object's attribute template // rc = template_copy(tmpl, old_obj->template); if (rc != CKR_OK) { goto error; } rc = template_add_attributes(new_tmpl, pTemplate, ulCount); if (rc != CKR_OK) { goto error; } // at this point, the new object has the list of attributes. we need // to do some more checking now: // 1) invalid attribute values // 2) missing required attributes // 3) attributes inappropriate for the object class // 4) conflicting attributes/values // found = template_get_class(tmpl, &class, &subclass); if (found == FALSE) { rc = CKR_TEMPLATE_INCONSISTENT; goto error; } // The user cannot change object classes so we assume the existing // object attributes are valid. we still need to check the new // attributes. We cannot merge the new attributes in with the // old ones and then check for validity because some attributes // are added internally and are not allowed to be specified by // the user (ie. CKA_LOCAL for key types) but may still be part // of the old template. rc = template_validate_attributes(new_tmpl, class, subclass, MODE_COPY); if (rc != CKR_OK) goto error; rc = template_merge(tmpl, &new_tmpl); if (rc != CKR_OK) { goto error; } rc = template_check_required_attributes(tmpl, class, subclass, MODE_COPY); if (rc != CKR_OK) goto error; o->template = tmpl; *new_obj = o; return (CKR_OK); error: if (tmpl) (void) template_free(tmpl); if (new_tmpl) (void) template_free(new_tmpl); if (o) (void) object_free(o); return (rc); } CK_RV object_flatten(OBJECT * obj, CK_BYTE ** data, UINT32 *len) { CK_BYTE * buf = NULL; CK_ULONG_32 tmpl_len, total_len; CK_ULONG_32 offset; CK_ULONG_32 count; long rc; if (! obj) { return (CKR_FUNCTION_FAILED); } count = template_get_count(obj->template); tmpl_len = template_get_compressed_size(obj->template); total_len = tmpl_len + sizeof (CK_OBJECT_CLASS_32) + sizeof (CK_ULONG_32) + 8; buf = (CK_BYTE *)malloc(total_len); if (!buf) { return (CKR_HOST_MEMORY); } (void) memset((CK_BYTE *)buf, 0x0, total_len); offset = 0; (void) memcpy(buf + offset, &obj->class, sizeof (CK_OBJECT_CLASS_32)); offset += sizeof (CK_OBJECT_CLASS_32); (void) memcpy(buf + offset, &count, sizeof (CK_ULONG_32)); offset += sizeof (CK_ULONG_32); (void) memcpy(buf + offset, &obj->name, sizeof (CK_BYTE) * 8); offset += 8; rc = template_flatten(obj->template, buf + offset); if (rc != CKR_OK) { free(buf); return (rc); } *data = buf; *len = total_len; return (CKR_OK); } CK_BBOOL object_free(OBJECT *obj) { (void) template_free(obj->template); free(obj); return (TRUE); } // object_is_modifiable() // CK_BBOOL object_is_modifiable(OBJECT *obj) { CK_ATTRIBUTE * attr = NULL; CK_BBOOL modifiable; CK_BBOOL found; found = template_attribute_find(obj->template, CKA_MODIFIABLE, &attr); if (found == FALSE) return (TRUE); modifiable = *(CK_BBOOL *)attr->pValue; return (modifiable); } // object_is_private() // // an is_private member should probably be added to OBJECT // CK_BBOOL object_is_private(OBJECT *obj) { CK_ATTRIBUTE * attr = NULL; CK_BBOOL priv; CK_BBOOL found; found = template_attribute_find(obj->template, CKA_PRIVATE, &attr); if (found == FALSE) return (TRUE); if (attr == NULL) return (TRUE); priv = *((CK_BBOOL *)attr->pValue); return (priv); } CK_BBOOL object_is_public(OBJECT *obj) { CK_BBOOL rc; rc = object_is_private(obj); if (rc) return (FALSE); return (TRUE); } CK_BBOOL object_is_token_object(OBJECT *obj) { CK_ATTRIBUTE * attr = NULL; CK_BBOOL is_token; CK_BBOOL found; found = template_attribute_find(obj->template, CKA_TOKEN, &attr); if (found == FALSE) return (FALSE); is_token = *(CK_BBOOL *)attr->pValue; return (is_token); } CK_BBOOL object_is_session_object(OBJECT *obj) { CK_BBOOL rc; rc = object_is_token_object(obj); if (rc) return (FALSE); else return (TRUE); } CK_ULONG object_get_size(OBJECT *obj) { CK_ULONG size; size = sizeof (OBJECT) + template_get_size(obj->template); return (size); } CK_RV object_get_attribute_values(OBJECT * obj, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount) { TEMPLATE *obj_tmpl = NULL; CK_ATTRIBUTE *attr = NULL; CK_ULONG i; CK_BBOOL flag; CK_RV rc; rc = CKR_OK; obj_tmpl = obj->template; for (i = 0; i < ulCount; i++) { flag = template_check_exportability(obj_tmpl, pTemplate[i].type); if (flag == FALSE) { rc = CKR_ATTRIBUTE_SENSITIVE; pTemplate[i].ulValueLen = (CK_ULONG) - 1; continue; } flag = template_attribute_find(obj_tmpl, pTemplate[i].type, &attr); if (flag == FALSE) { rc = CKR_ATTRIBUTE_TYPE_INVALID; pTemplate[i].ulValueLen = (CK_ULONG) - 1; continue; } if (pTemplate[i].pValue == NULL) { pTemplate[i].ulValueLen = attr->ulValueLen; } else if (pTemplate[i].ulValueLen >= attr->ulValueLen) { (void) memcpy(pTemplate[i].pValue, attr->pValue, attr->ulValueLen); pTemplate[i].ulValueLen = attr->ulValueLen; } else { rc = CKR_BUFFER_TOO_SMALL; pTemplate[i].ulValueLen = (CK_ULONG) - 1; } } return (rc); } CK_RV object_set_attribute_values(OBJECT * obj, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount) { TEMPLATE * new_tmpl; CK_BBOOL found; CK_ULONG class, subclass; CK_RV rc; if (! obj || ! pTemplate) { return (CKR_FUNCTION_FAILED); } found = template_get_class(obj->template, &class, &subclass); if (found == FALSE) { rc = CKR_FUNCTION_FAILED; goto error; } new_tmpl = (TEMPLATE *)malloc(sizeof (TEMPLATE)); if (! new_tmpl) { return (CKR_HOST_MEMORY); } (void) memset(new_tmpl, 0x0, sizeof (TEMPLATE)); rc = template_add_attributes(new_tmpl, pTemplate, ulCount); if (rc != CKR_OK) { goto error; } rc = template_validate_attributes(new_tmpl, class, subclass, MODE_MODIFY); if (rc != CKR_OK) { goto error; } rc = template_merge(obj->template, &new_tmpl); if (rc != CKR_OK) { return (rc); } return (CKR_OK); error: if (new_tmpl) (void) template_free(new_tmpl); return (rc); } CK_RV object_restore(CK_BYTE *data, OBJECT **new_obj, CK_BBOOL replace) { TEMPLATE * tmpl = NULL; OBJECT * obj = NULL; CK_ULONG offset = 0; CK_ULONG_32 count = 0; CK_RV rc; if (! data || ! new_obj) { return (CKR_FUNCTION_FAILED); } obj = (OBJECT *)malloc(sizeof (OBJECT)); if (! obj) { rc = CKR_HOST_MEMORY; goto error; } (void) memset(obj, 0x0, sizeof (OBJECT)); (void) memcpy(&obj->class, data + offset, sizeof (CK_OBJECT_CLASS_32)); offset += sizeof (CK_OBJECT_CLASS_32); (void) memcpy(&count, data + offset, sizeof (CK_ULONG_32)); offset += sizeof (CK_ULONG_32); (void) memcpy(&obj->name, data + offset, 8); offset += 8; rc = template_unflatten(&tmpl, data + offset, count); if (rc != CKR_OK) { goto error; } obj->template = tmpl; if (replace == FALSE) { *new_obj = obj; } else { (void) template_free((*new_obj)->template); (void) memcpy(*new_obj, obj, sizeof (OBJECT)); free(obj); } return (CKR_OK); error: if (obj) (void) object_free(obj); if (tmpl) (void) template_free(tmpl); return (rc); } // // CK_RV object_create_skel(CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount, CK_ULONG mode, CK_ULONG class, CK_ULONG subclass, OBJECT ** obj) { TEMPLATE * tmpl = NULL; TEMPLATE * tmpl2 = NULL; OBJECT * o = NULL; CK_RV rc; if (! obj) { return (CKR_FUNCTION_FAILED); } if (! pTemplate && (ulCount != 0)) { return (CKR_FUNCTION_FAILED); } o = (OBJECT *)malloc(sizeof (OBJECT)); tmpl = (TEMPLATE *)malloc(sizeof (TEMPLATE)); tmpl2 = (TEMPLATE *)malloc(sizeof (TEMPLATE)); if (! o || ! tmpl || ! tmpl2) { rc = CKR_HOST_MEMORY; goto done; } (void) memset(o, 0x0, sizeof (OBJECT)); (void) memset(tmpl, 0x0, sizeof (TEMPLATE)); (void) memset(tmpl2, 0x0, sizeof (TEMPLATE)); rc = template_add_default_attributes(tmpl, class, subclass, mode); if (rc != CKR_OK) goto done; rc = template_add_attributes(tmpl2, pTemplate, ulCount); if (rc != CKR_OK) goto done; // at this point, the new template has the list of attributes. we need // to do some more checking now: // 1) invalid attribute values // 2) missing required attributes // 3) attributes inappropriate for the object class // 4) conflicting attributes/values // rc = template_validate_attributes(tmpl2, class, subclass, mode); if (rc != CKR_OK) { goto done; } rc = template_check_required_attributes(tmpl2, class, subclass, mode); if (rc != CKR_OK) { goto done; } rc = template_merge(tmpl, &tmpl2); if (rc != CKR_OK) { goto done; } // at this point, we should have a valid object with correct attributes // o->template = tmpl; *obj = o; return (CKR_OK); done: if (o) free(o); if (tmpl) (void) template_free(tmpl); if (tmpl2) (void) template_free(tmpl2); return (rc); } /* * Common Public License Version 0.5 * * THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF * THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, * REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES * RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. * * 1. DEFINITIONS * * "Contribution" means: * a) in the case of the initial Contributor, the * initial code and documentation distributed under * this Agreement, and * * b) in the case of each subsequent Contributor: * i) changes to the Program, and * ii) additions to the Program; * * where such changes and/or additions to the Program * originate from and are distributed by that * particular Contributor. A Contribution 'originates' * from a Contributor if it was added to the Program * by such Contributor itself or anyone acting on such * Contributor's behalf. Contributions do not include * additions to the Program which: (i) are separate * modules of software distributed in conjunction with * the Program under their own license agreement, and * (ii) are not derivative works of the Program. * * * "Contributor" means any person or entity that distributes * the Program. * * "Licensed Patents " mean patent claims licensable by a * Contributor which are necessarily infringed by the use or * sale of its Contribution alone or when combined with the * Program. * * "Program" means the Contributions distributed in * accordance with this Agreement. * * "Recipient" means anyone who receives the Program under * this Agreement, including all Contributors. * * 2. GRANT OF RIGHTS * * a) Subject to the terms of this Agreement, each * Contributor hereby grants Recipient a * no - exclusive, worldwide, royalt - free copyright * license to reproduce, prepare derivative works of, * publicly display, publicly perform, distribute and * sublicense the Contribution of such Contributor, if * any, and such derivative works, in source code and * object code form. * * b) Subject to the terms of this Agreement, each * Contributor hereby grants Recipient a * no - exclusive, worldwide, royalt - free patent * license under Licensed Patents to make, use, sell, * offer to sell, import and otherwise transfer the * Contribution of such Contributor, if any, in source * code and object code form. This patent license * shall apply to the combination of the Contribution * and the Program if, at the time the Contribution is * added by the Contributor, such addition of the * Contribution causes such combination to be covered * by the Licensed Patents. The patent license shall * not apply to any other combinations which include * the Contribution. No hardware per se is licensed * hereunder. * * c) Recipient understands that although each * Contributor grants the licenses to its * Contributions set forth herein, no assurances are * provided by any Contributor that the Program does * not infringe the patent or other intellectual * property rights of any other entity. Each * Contributor disclaims any liability to Recipient * for claims brought by any other entity based on * infringement of intellectual property rights or * otherwise. As a condition to exercising the rights * and licenses granted hereunder, each Recipient * hereby assumes sole responsibility to secure any * other intellectual property rights needed, if any. * * For example, if a third party patent license is * required to allow Recipient to distribute the * Program, it is Recipient's responsibility to * acquire that license before distributing the * Program. * * d) Each Contributor represents that to its * knowledge it has sufficient copyright rights in its * Contribution, if any, to grant the copyright * license set forth in this Agreement. * * 3. REQUIREMENTS * * A Contributor may choose to distribute the Program in * object code form under its own license agreement, provided * that: * a) it complies with the terms and conditions of * this Agreement; and * * b) its license agreement: * i) effectively disclaims on behalf of all * Contributors all warranties and conditions, express * and implied, including warranties or conditions of * title and no - infringement, and implied warranties * or conditions of merchantability and fitness for a * particular purpose; * * ii) effectively excludes on behalf of all * Contributors all liability for damages, including * direct, indirect, special, incidental and * consequential damages, such as lost profits; * * iii) states that any provisions which differ from * this Agreement are offered by that Contributor * alone and not by any other party; and * * iv) states that source code for the Program is * available from such Contributor, and informs * licensees how to obtain it in a reasonable manner * on or through a medium customarily used for * software exchange. * * When the Program is made available in source code form: * a) it must be made available under this Agreement; * and * b) a copy of this Agreement must be included with * each copy of the Program. * * Contributors may not remove or alter any copyright notices * contained within the Program. * * Each Contributor must identify itself as the originator of * its Contribution, if any, in a manner that reasonably * allows subsequent Recipients to identify the originator of * the Contribution. * * * 4. COMMERCIAL DISTRIBUTION * * Commercial distributors of software may accept certain * responsibilities with respect to end users, business * partners and the like. While this license is intended to * facilitate the commercial use of the Program, the * Contributor who includes the Program in a commercial * product offering should do so in a manner which does not * create potential liability for other Contributors. * Therefore, if a Contributor includes the Program in a * commercial product offering, such Contributor ("Commercial * Contributor") hereby agrees to defend and indemnify every * other Contributor ("Indemnified Contributor") against any * losses, damages and costs (collectively "Losses") arising * from claims, lawsuits and other legal actions brought by a * third party against the Indemnified Contributor to the * extent caused by the acts or omissions of such Commercial * Contributor in connection with its distribution of the * Program in a commercial product offering. The obligations * in this section do not apply to any claims or Losses * relating to any actual or alleged intellectual property * infringement. In order to qualify, an Indemnified * Contributor must: a) promptly notify the Commercial * Contributor in writing of such claim, and b) allow the * Commercial Contributor to control, and cooperate with the * Commercial Contributor in, the defense and any related * settlement negotiations. The Indemnified Contributor may * participate in any such claim at its own expense. * * * For example, a Contributor might include the Program in a * commercial product offering, Product X. That Contributor * is then a Commercial Contributor. If that Commercial * Contributor then makes performance claims, or offers * warranties related to Product X, those performance claims * and warranties are such Commercial Contributor's * responsibility alone. Under this section, the Commercial * Contributor would have to defend claims against the other * Contributors related to those performance claims and * warranties, and if a court requires any other Contributor * to pay any damages as a result, the Commercial Contributor * must pay those damages. * * * 5. NO WARRANTY * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE * PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR * IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR * CONDITIONS OF TITLE, NO - INFRINGEMENT, MERCHANTABILITY OR * FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely * responsible for determining the appropriateness of using * and distributing the Program and assumes all risks * associated with its exercise of rights under this * Agreement, including but not limited to the risks and * costs of program errors, compliance with applicable laws, * damage to or loss of data, programs or equipment, and * unavailability or interruption of operations. * * 6. DISCLAIMER OF LIABILITY * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER * RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION * LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE * OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * 7. GENERAL * * If any provision of this Agreement is invalid or * unenforceable under applicable law, it shall not affect * the validity or enforceability of the remainder of the * terms of this Agreement, and without further action by the * parties hereto, such provision shall be reformed to the * minimum extent necessary to make such provision valid and * enforceable. * * * If Recipient institutes patent litigation against a * Contributor with respect to a patent applicable to * software (including a cros - claim or counterclaim in a * lawsuit), then any patent licenses granted by that * Contributor to such Recipient under this Agreement shall * terminate as of the date such litigation is filed. In * addition, If Recipient institutes patent litigation * against any entity (including a cros - claim or * counterclaim in a lawsuit) alleging that the Program * itself (excluding combinations of the Program with other * software or hardware) infringes such Recipient's * patent(s), then such Recipient's rights granted under * Section 2(b) shall terminate as of the date such * litigation is filed. * * All Recipient's rights under this Agreement shall * terminate if it fails to comply with any of the material * terms or conditions of this Agreement and does not cure * such failure in a reasonable period of time after becoming * aware of such noncompliance. If all Recipient's rights * under this Agreement terminate, Recipient agrees to cease * use and distribution of the Program as soon as reasonably * practicable. However, Recipient's obligations under this * Agreement and any licenses granted by Recipient relating * to the Program shall continue and survive. * * Everyone is permitted to copy and distribute copies of * this Agreement, but in order to avoid inconsistency the * Agreement is copyrighted and may only be modified in the * following manner. The Agreement Steward reserves the right * to publish new versions (including revisions) of this * Agreement from time to time. No one other than the * Agreement Steward has the right to modify this Agreement. * * IBM is the initial Agreement Steward. IBM may assign the * responsibility to serve as the Agreement Steward to a * suitable separate entity. Each new version of the * Agreement will be given a distinguishing version number. * The Program (including Contributions) may always be * distributed subject to the version of the Agreement under * which it was received. In addition, after a new version of * the Agreement is published, Contributor may elect to * distribute the Program (including its Contributions) under * the new version. Except as expressly stated in Sections * 2(a) and 2(b) above, Recipient receives no rights or * licenses to the intellectual property of any Contributor * under this Agreement, whether expressly, by implication, * estoppel or otherwise. All rights in the Program not * expressly granted under this Agreement are reserved. * * * This Agreement is governed by the laws of the State of New * York and the intellectual property laws of the United * States of America. No party to this Agreement will bring a * legal action under this Agreement more than one year after * the cause of action arose. Each party waives its rights to * a jury trial in any resulting litigation. * * * * (C) COPYRIGHT International Business Machines Corp. 2001, 2002 */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include "tpmtok_int.h" SESSION * session_mgr_find(CK_SESSION_HANDLE handle) { DL_NODE * node = NULL; SESSION * result = NULL; CK_RV rc; rc = pthread_mutex_lock(&sess_list_mutex); if (rc != CKR_OK) { return (NULL); } node = sess_list; while (node) { SESSION *s = (SESSION *)node->data; if (s->handle == handle) { result = s; break; } node = node->next; } (void) pthread_mutex_unlock(&sess_list_mutex); return (result); } /* * session_mgr_new() * * creates a new session structure and adds it to the process's list * of sessions * * Args: CK_ULONG flags : session flags (INPUT) * SESSION ** sess : new session pointer (OUTPUT) * * Returns: CK_RV */ CK_RV session_mgr_new(CK_ULONG flags, SESSION **sess) { SESSION * new_session = NULL; SESSION * s = NULL; DL_NODE * node = NULL; CK_BBOOL user_session = FALSE; CK_BBOOL so_session = FALSE; CK_BBOOL pkcs_locked = TRUE; CK_BBOOL sess_locked = TRUE; CK_RV rc; new_session = (SESSION *)malloc(sizeof (SESSION)); if (! new_session) { rc = CKR_HOST_MEMORY; goto done; } (void) memset(new_session, 0x0, sizeof (SESSION)); rc = pthread_mutex_lock(&pkcs_mutex); if (rc != CKR_OK) { return (rc); } pkcs_locked = TRUE; do { s = session_mgr_find(next_session_handle); if (s != NULL) next_session_handle++; else new_session->handle = next_session_handle++; } while (s != NULL); (void) pthread_mutex_unlock(&pkcs_mutex); pkcs_locked = FALSE; new_session->session_info.slotID = 1; new_session->session_info.flags = flags; new_session->session_info.ulDeviceError = 0; rc = pthread_mutex_lock(&sess_list_mutex); if (rc != CKR_OK) { return (rc); } sess_locked = TRUE; node = sess_list; while (node) { SESSION *s = (SESSION *)node->data; if (s->session_info.state == CKS_RW_SO_FUNCTIONS) { so_session = TRUE; break; } if ((s->session_info.state == CKS_RO_USER_FUNCTIONS) || (s->session_info.state == CKS_RW_USER_FUNCTIONS)) { user_session = TRUE; break; } node = node->next; } if (global_login_state == CKS_RW_SO_FUNCTIONS) { so_session = TRUE; } if ((global_login_state == CKS_RO_USER_FUNCTIONS) || (global_login_state == CKS_RW_USER_FUNCTIONS)) { user_session = TRUE; } if (user_session) { if (new_session->session_info.flags & CKF_RW_SESSION) new_session->session_info.state = CKS_RW_USER_FUNCTIONS; else new_session->session_info.state = CKS_RO_USER_FUNCTIONS; } else if (so_session) { new_session->session_info.state = CKS_RW_SO_FUNCTIONS; } else { if (new_session->session_info.flags & CKF_RW_SESSION) new_session->session_info.state = CKS_RW_PUBLIC_SESSION; else new_session->session_info.state = CKS_RO_PUBLIC_SESSION; } sess_list = dlist_add_as_first(sess_list, new_session); *sess = new_session; done: if (pkcs_locked) (void) pthread_mutex_unlock(&pkcs_mutex); if (sess_locked) (void) pthread_mutex_unlock(&sess_list_mutex); if (rc != CKR_OK && new_session != NULL) { free(new_session); } return (rc); } CK_BBOOL session_mgr_so_session_exists(void) { DL_NODE *node = NULL; CK_RV rc; rc = pthread_mutex_lock(&sess_list_mutex); if (rc != CKR_OK) { return (rc); } node = sess_list; while (node) { SESSION *s = (SESSION *)node->data; if (s->session_info.state == CKS_RW_SO_FUNCTIONS) { rc = TRUE; goto done; } node = node->next; } rc = FALSE; done: (void) pthread_mutex_unlock(&sess_list_mutex); return (rc); } CK_BBOOL session_mgr_user_session_exists(void) { DL_NODE *node = NULL; CK_RV rc; rc = pthread_mutex_lock(&sess_list_mutex); if (rc != CKR_OK) { return (rc); } node = sess_list; while (node) { SESSION *s = (SESSION *)node->data; if ((s->session_info.state == CKS_RO_USER_FUNCTIONS) || (s->session_info.state == CKS_RW_USER_FUNCTIONS)) { rc = TRUE; goto done; } node = node->next; } rc = FALSE; done: (void) pthread_mutex_unlock(&sess_list_mutex); return (rc); } CK_BBOOL session_mgr_public_session_exists(void) { DL_NODE *node = NULL; CK_RV rc; rc = pthread_mutex_lock(&sess_list_mutex); if (rc != CKR_OK) { return (rc); } node = sess_list; while (node) { SESSION *s = (SESSION *)node->data; if ((s->session_info.state == CKS_RO_PUBLIC_SESSION) || (s->session_info.state == CKS_RW_PUBLIC_SESSION)) { rc = TRUE; goto done; } node = node->next; } rc = FALSE; done: (void) pthread_mutex_unlock(&sess_list_mutex); return (rc); } CK_BBOOL session_mgr_readonly_exists(void) { DL_NODE *node = NULL; CK_RV rc; rc = pthread_mutex_lock(&sess_list_mutex); if (rc != CKR_OK) { return (rc); } node = sess_list; while (node) { SESSION *s = (SESSION *)node->data; if ((s->session_info.flags & CKF_RW_SESSION) == 0) { rc = TRUE; goto done; } node = node->next; } rc = FALSE; done: (void) pthread_mutex_unlock(&sess_list_mutex); return (rc); } CK_RV session_mgr_close_session(SESSION *sess) { DL_NODE * node = NULL; CK_RV rc = CKR_OK; if (! sess) return (FALSE); rc = pthread_mutex_lock(&sess_list_mutex); if (rc != CKR_OK) { return (CKR_FUNCTION_FAILED); } node = dlist_find(sess_list, sess); if (! node) { rc = CKR_FUNCTION_FAILED; goto done; } (void) object_mgr_purge_session_objects(sess, ALL); if (sess->find_list) free(sess->find_list); if (sess->encr_ctx.context) free(sess->encr_ctx.context); if (sess->encr_ctx.mech.pParameter) free(sess->encr_ctx.mech.pParameter); if (sess->decr_ctx.context) free(sess->decr_ctx.context); if (sess->decr_ctx.mech.pParameter) free(sess->decr_ctx.mech.pParameter); if (sess->digest_ctx.context.ref) free(sess->digest_ctx.context.ref); if (sess->digest_ctx.mech.pParameter) free(sess->digest_ctx.mech.pParameter); if (sess->sign_ctx.context) free(sess->sign_ctx.context); if (sess->sign_ctx.mech.pParameter) free(sess->sign_ctx.mech.pParameter); if (sess->verify_ctx.context) free(sess->verify_ctx.context); if (sess->verify_ctx.mech.pParameter) free(sess->verify_ctx.mech.pParameter); if (sess->hContext) (void) Tspi_Context_Close(sess->hContext); free(sess); sess_list = dlist_remove_node(sess_list, node); if (sess_list == NULL) { TSS_HCONTEXT hContext; if (open_tss_context(&hContext) == 0) { (void) object_mgr_purge_private_token_objects(hContext); (void) Tspi_Context_Close(hContext); } global_login_state = 0; (void) pthread_mutex_lock(&obj_list_mutex); (void) object_mgr_purge_map((SESSION *)0xFFFF, PRIVATE); (void) pthread_mutex_unlock(&obj_list_mutex); } done: (void) pthread_mutex_unlock(&sess_list_mutex); return (rc); } // session_mgr_close_all_sessions() // // removes all sessions from the specified process // CK_RV session_mgr_close_all_sessions(void) { CK_RV rc = CKR_OK; rc = pthread_mutex_lock(&sess_list_mutex); if (rc != CKR_OK) { return (CKR_FUNCTION_FAILED); } while (sess_list) { SESSION *sess = (SESSION *)sess_list->data; (void) object_mgr_purge_session_objects(sess, ALL); if (sess->find_list) free(sess->find_list); if (sess->encr_ctx.context) free(sess->encr_ctx.context); if (sess->encr_ctx.mech.pParameter) free(sess->encr_ctx.mech.pParameter); if (sess->decr_ctx.context) free(sess->decr_ctx.context); if (sess->decr_ctx.mech.pParameter) free(sess->decr_ctx.mech.pParameter); if (sess->digest_ctx.context.ref) free(sess->digest_ctx.context.ref); if (sess->digest_ctx.mech.pParameter) free(sess->digest_ctx.mech.pParameter); if (sess->sign_ctx.context) free(sess->sign_ctx.context); if (sess->sign_ctx.mech.pParameter) free(sess->sign_ctx.mech.pParameter); if (sess->verify_ctx.context) free(sess->verify_ctx.context); if (sess->verify_ctx.mech.pParameter) free(sess->verify_ctx.mech.pParameter); if (sess->hContext) (void) Tspi_Context_Close(sess->hContext); free(sess); sess_list = dlist_remove_node(sess_list, sess_list); } (void) pthread_mutex_unlock(&sess_list_mutex); return (CKR_OK); } // session_mgr_login_all() // // changes the login status of all sessions in the token // // Arg: CK_USER_TYPE user_type : USER or SO // CK_RV session_mgr_login_all(CK_USER_TYPE user_type) { DL_NODE * node = NULL; CK_RV rc = CKR_OK; rc = pthread_mutex_lock(&sess_list_mutex); if (rc != CKR_OK) { return (CKR_FUNCTION_FAILED); } node = sess_list; while (node) { SESSION *s = (SESSION *)node->data; if (s->session_info.flags & CKF_RW_SESSION) { if (user_type == CKU_USER) s->session_info.state = CKS_RW_USER_FUNCTIONS; else s->session_info.state = CKS_RW_SO_FUNCTIONS; } else { if (user_type == CKU_USER) s->session_info.state = CKS_RO_USER_FUNCTIONS; } global_login_state = s->session_info.state; node = node->next; } (void) pthread_mutex_unlock(&sess_list_mutex); return (CKR_OK); } CK_RV session_mgr_logout_all(void) { DL_NODE * node = NULL; SESSION * s = NULL; CK_RV rc = CKR_OK; rc = pthread_mutex_lock(&sess_list_mutex); if (rc != CKR_OK) { return (CKR_FUNCTION_FAILED); } node = sess_list; while (node) { s = (SESSION *)node->data; (void) object_mgr_purge_session_objects(s, PRIVATE); if (s->session_info.flags & CKF_RW_SESSION) s->session_info.state = CKS_RW_PUBLIC_SESSION; else s->session_info.state = CKS_RO_PUBLIC_SESSION; global_login_state = s->session_info.state; // SAB node = node->next; } (void) pthread_mutex_unlock(&sess_list_mutex); return (CKR_OK); } CK_RV session_mgr_get_op_state(SESSION *sess, CK_BBOOL length_only, CK_BYTE *data, CK_ULONG *data_len) { OP_STATE_DATA *op_data = NULL; CK_ULONG op_data_len = 0; CK_ULONG offset; void *dptr = data; if (! sess) { return (CKR_FUNCTION_FAILED); } if (sess->find_active == TRUE) { return (CKR_STATE_UNSAVEABLE); } if (sess->encr_ctx.active == TRUE) { if (op_data != NULL) { return (CKR_STATE_UNSAVEABLE); } op_data_len = sizeof (OP_STATE_DATA) + sizeof (ENCR_DECR_CONTEXT) + sess->encr_ctx.context_len + sess->encr_ctx.mech.ulParameterLen; if (length_only == FALSE) { op_data = (OP_STATE_DATA *)dptr; op_data->data_len = op_data_len - sizeof (OP_STATE_DATA); op_data->session_state = sess->session_info.state; op_data->active_operation = STATE_ENCR; offset = sizeof (OP_STATE_DATA); (void) (void) memcpy((CK_BYTE *)op_data + offset, &sess->encr_ctx, sizeof (ENCR_DECR_CONTEXT)); offset += sizeof (ENCR_DECR_CONTEXT); if (sess->encr_ctx.context_len != 0) { (void) memcpy((CK_BYTE *)op_data + offset, sess->encr_ctx.context, sess->encr_ctx.context_len); offset += sess->encr_ctx.context_len; } if (sess->encr_ctx.mech.ulParameterLen != 0) { (void) memcpy((CK_BYTE *)op_data + offset, sess->encr_ctx.mech.pParameter, sess->encr_ctx.mech.ulParameterLen); } } } if (sess->decr_ctx.active == TRUE) { if (op_data != NULL) { return (CKR_STATE_UNSAVEABLE); } op_data_len = sizeof (OP_STATE_DATA) + sizeof (ENCR_DECR_CONTEXT) + sess->decr_ctx.context_len + sess->decr_ctx.mech.ulParameterLen; if (length_only == FALSE) { op_data = (OP_STATE_DATA *)dptr; op_data->data_len = op_data_len - sizeof (OP_STATE_DATA); op_data->session_state = sess->session_info.state; op_data->active_operation = STATE_DECR; offset = sizeof (OP_STATE_DATA); (void) memcpy((CK_BYTE *)op_data + offset, &sess->decr_ctx, sizeof (ENCR_DECR_CONTEXT)); offset += sizeof (ENCR_DECR_CONTEXT); if (sess->decr_ctx.context_len != 0) { (void) memcpy((CK_BYTE *)op_data + offset, sess->decr_ctx.context, sess->decr_ctx.context_len); offset += sess->decr_ctx.context_len; } if (sess->decr_ctx.mech.ulParameterLen != 0) { (void) memcpy((CK_BYTE *)op_data + offset, sess->decr_ctx.mech.pParameter, sess->decr_ctx.mech.ulParameterLen); } } } if (sess->digest_ctx.active == TRUE) { if (op_data != NULL) { return (CKR_STATE_UNSAVEABLE); } op_data_len = sizeof (OP_STATE_DATA) + sizeof (DIGEST_CONTEXT) + sess->digest_ctx.context_len + sess->digest_ctx.mech.ulParameterLen; if (length_only == FALSE) { op_data = (OP_STATE_DATA *)dptr; op_data->data_len = op_data_len - sizeof (OP_STATE_DATA); op_data->session_state = sess->session_info.state; op_data->active_operation = STATE_DIGEST; offset = sizeof (OP_STATE_DATA); (void) memcpy((CK_BYTE *)op_data + offset, &sess->digest_ctx, sizeof (DIGEST_CONTEXT)); offset += sizeof (DIGEST_CONTEXT); if (sess->digest_ctx.context_len != 0) { (void) memcpy((CK_BYTE *)op_data + offset, sess->digest_ctx.context.ref, sess->digest_ctx.context_len); offset += sess->digest_ctx.context_len; } if (sess->digest_ctx.mech.ulParameterLen != 0) { (void) memcpy((CK_BYTE *)op_data + offset, sess->digest_ctx.mech.pParameter, sess->digest_ctx.mech.ulParameterLen); } } } if (sess->sign_ctx.active == TRUE) { if (op_data != NULL) { return (CKR_STATE_UNSAVEABLE); } op_data_len = sizeof (OP_STATE_DATA) + sizeof (SIGN_VERIFY_CONTEXT) + sess->sign_ctx.context_len + sess->sign_ctx.mech.ulParameterLen; if (length_only == FALSE) { op_data = (OP_STATE_DATA *)dptr; op_data->data_len = op_data_len - sizeof (OP_STATE_DATA); op_data->session_state = sess->session_info.state; op_data->active_operation = STATE_SIGN; offset = sizeof (OP_STATE_DATA); (void) memcpy((CK_BYTE *)op_data + offset, &sess->sign_ctx, sizeof (SIGN_VERIFY_CONTEXT)); offset += sizeof (SIGN_VERIFY_CONTEXT); if (sess->sign_ctx.context_len != 0) { (void) memcpy((CK_BYTE *)op_data + offset, sess->sign_ctx.context, sess->sign_ctx.context_len); offset += sess->sign_ctx.context_len; } if (sess->sign_ctx.mech.ulParameterLen != 0) { (void) memcpy((CK_BYTE *)op_data + offset, sess->sign_ctx.mech.pParameter, sess->sign_ctx.mech.ulParameterLen); } } } if (sess->verify_ctx.active == TRUE) { if (op_data != NULL) { return (CKR_STATE_UNSAVEABLE); } op_data_len = sizeof (OP_STATE_DATA) + sizeof (SIGN_VERIFY_CONTEXT) + sess->verify_ctx.context_len + sess->verify_ctx.mech.ulParameterLen; if (length_only == FALSE) { op_data = (OP_STATE_DATA *)dptr; op_data->data_len = op_data_len - sizeof (OP_STATE_DATA); op_data->session_state = sess->session_info.state; op_data->active_operation = STATE_SIGN; offset = sizeof (OP_STATE_DATA); (void) memcpy((CK_BYTE *)op_data + offset, &sess->verify_ctx, sizeof (SIGN_VERIFY_CONTEXT)); offset += sizeof (SIGN_VERIFY_CONTEXT); if (sess->verify_ctx.context_len != 0) { (void) memcpy((CK_BYTE *)op_data + offset, sess->verify_ctx.context, sess->verify_ctx.context_len); offset += sess->verify_ctx.context_len; } if (sess->verify_ctx.mech.ulParameterLen != 0) { (void) memcpy((CK_BYTE *)op_data + offset, sess->verify_ctx.mech.pParameter, sess->verify_ctx.mech.ulParameterLen); } } } *data_len = op_data_len; return (CKR_OK); } CK_RV session_mgr_set_op_state( SESSION *sess, CK_OBJECT_HANDLE encr_key, CK_OBJECT_HANDLE auth_key, CK_BYTE *data) { OP_STATE_DATA *op_data = NULL; CK_BYTE *mech_param = NULL; CK_BYTE *context = NULL; CK_BYTE *ptr1 = NULL; CK_BYTE *ptr2 = NULL; CK_BYTE *ptr3 = NULL; CK_ULONG len; void *dptr = data; if (! sess || ! data) { return (CKR_FUNCTION_FAILED); } op_data = (OP_STATE_DATA *)dptr; if (sess->session_info.state != op_data->session_state) { return (CKR_SAVED_STATE_INVALID); } switch (op_data->active_operation) { case STATE_ENCR: case STATE_DECR: { void *cptr = data + sizeof (OP_STATE_DATA); ENCR_DECR_CONTEXT *ctx = (ENCR_DECR_CONTEXT *)cptr; len = sizeof (ENCR_DECR_CONTEXT) + ctx->context_len + ctx->mech.ulParameterLen; if (len != op_data->data_len) { return (CKR_SAVED_STATE_INVALID); } if (auth_key != 0) { return (CKR_KEY_NOT_NEEDED); } if (encr_key == 0) { return (CKR_KEY_NEEDED); } ptr1 = (CK_BYTE *)ctx; ptr2 = ptr1 + sizeof (ENCR_DECR_CONTEXT); ptr3 = ptr2 + ctx->context_len; if (ctx->context_len) { context = (CK_BYTE *)malloc(ctx->context_len); if (! context) { return (CKR_HOST_MEMORY); } (void) memcpy(context, ptr2, ctx->context_len); } if (ctx->mech.ulParameterLen) { mech_param = (CK_BYTE *)malloc( ctx->mech.ulParameterLen); if (! mech_param) { if (context) free(context); return (CKR_HOST_MEMORY); } (void) memcpy(mech_param, ptr3, ctx->mech.ulParameterLen); } } break; case STATE_SIGN: case STATE_VERIFY: { void *cptr = data + sizeof (OP_STATE_DATA); SIGN_VERIFY_CONTEXT *ctx = (SIGN_VERIFY_CONTEXT *)cptr; len = sizeof (SIGN_VERIFY_CONTEXT) + ctx->context_len + ctx->mech.ulParameterLen; if (len != op_data->data_len) { return (CKR_SAVED_STATE_INVALID); } if (auth_key == 0) { return (CKR_KEY_NEEDED); } if (encr_key != 0) { return (CKR_KEY_NOT_NEEDED); } ptr1 = (CK_BYTE *)ctx; ptr2 = ptr1 + sizeof (SIGN_VERIFY_CONTEXT); ptr3 = ptr2 + ctx->context_len; if (ctx->context_len) { context = (CK_BYTE *)malloc(ctx->context_len); if (! context) { return (CKR_HOST_MEMORY); } (void) memcpy(context, ptr2, ctx->context_len); } if (ctx->mech.ulParameterLen) { mech_param = (CK_BYTE *)malloc( ctx->mech.ulParameterLen); if (! mech_param) { if (context) free(context); return (CKR_HOST_MEMORY); } (void) memcpy(mech_param, ptr3, ctx->mech.ulParameterLen); } } break; case STATE_DIGEST: { void *cptr = data + sizeof (OP_STATE_DATA); DIGEST_CONTEXT *ctx = (DIGEST_CONTEXT *)cptr; len = sizeof (DIGEST_CONTEXT) + ctx->context_len + ctx->mech.ulParameterLen; if (len != op_data->data_len) { return (CKR_SAVED_STATE_INVALID); } if (auth_key != 0) { return (CKR_KEY_NOT_NEEDED); } if (encr_key != 0) { return (CKR_KEY_NOT_NEEDED); } ptr1 = (CK_BYTE *)ctx; ptr2 = ptr1 + sizeof (DIGEST_CONTEXT); ptr3 = ptr2 + ctx->context_len; if (ctx->context_len) { context = (CK_BYTE *)malloc(ctx->context_len); if (! context) { return (CKR_HOST_MEMORY); } (void) memcpy(context, ptr2, ctx->context_len); } if (ctx->mech.ulParameterLen) { mech_param = (CK_BYTE *)malloc( ctx->mech.ulParameterLen); if (! mech_param) { if (context) free(context); return (CKR_HOST_MEMORY); } (void) memcpy(mech_param, ptr3, ctx->mech.ulParameterLen); } } break; default: return (CKR_SAVED_STATE_INVALID); } if (sess->encr_ctx.active) (void) encr_mgr_cleanup(&sess->encr_ctx); if (sess->decr_ctx.active) (void) decr_mgr_cleanup(&sess->decr_ctx); if (sess->digest_ctx.active) (void) digest_mgr_cleanup(&sess->digest_ctx); if (sess->sign_ctx.active) (void) sign_mgr_cleanup(&sess->sign_ctx); if (sess->verify_ctx.active) (void) verify_mgr_cleanup(&sess->verify_ctx); switch (op_data->active_operation) { case STATE_ENCR: (void) memcpy(&sess->encr_ctx, ptr1, sizeof (ENCR_DECR_CONTEXT)); sess->encr_ctx.key = encr_key; sess->encr_ctx.context = context; sess->encr_ctx.mech.pParameter = mech_param; break; case STATE_DECR: (void) memcpy(&sess->decr_ctx, ptr1, sizeof (ENCR_DECR_CONTEXT)); sess->decr_ctx.key = encr_key; sess->decr_ctx.context = context; sess->decr_ctx.mech.pParameter = mech_param; break; case STATE_SIGN: (void) memcpy(&sess->sign_ctx, ptr1, sizeof (SIGN_VERIFY_CONTEXT)); sess->sign_ctx.key = auth_key; sess->sign_ctx.context = context; sess->sign_ctx.mech.pParameter = mech_param; break; case STATE_VERIFY: (void) memcpy(&sess->verify_ctx, ptr1, sizeof (SIGN_VERIFY_CONTEXT)); sess->verify_ctx.key = auth_key; sess->verify_ctx.context = context; sess->verify_ctx.mech.pParameter = mech_param; break; case STATE_DIGEST: (void) memcpy(&sess->digest_ctx, ptr1, sizeof (DIGEST_CONTEXT)); sess->digest_ctx.context.ref = context; sess->digest_ctx.mech.pParameter = mech_param; break; } return (CKR_OK); } CK_BBOOL pin_expired(CK_SESSION_INFO *si, CK_FLAGS flags) { // If this is an SO session if ((flags & CKF_SO_PIN_TO_BE_CHANGED) && (si->state == CKS_RW_SO_FUNCTIONS)) return (TRUE); return ((flags & CKF_USER_PIN_TO_BE_CHANGED) && ((si->state == CKS_RO_USER_FUNCTIONS) || (si->state == CKS_RW_USER_FUNCTIONS))); } CK_BBOOL pin_locked(CK_SESSION_INFO *si, CK_FLAGS flags) { // If this is an SO session if ((flags & CKF_SO_PIN_LOCKED) && (si->state == CKS_RW_SO_FUNCTIONS)) return (TRUE); return ((flags & CKF_USER_PIN_LOCKED) && ((si->state == CKS_RO_USER_FUNCTIONS) || (si->state == CKS_RW_USER_FUNCTIONS))); } void set_login_flags(CK_USER_TYPE userType, CK_FLAGS *flags) { if (userType == CKU_USER) { if (*flags & CKF_USER_PIN_FINAL_TRY) { *flags |= CKF_USER_PIN_LOCKED; *flags &= ~(CKF_USER_PIN_FINAL_TRY); } else if (*flags & CKF_USER_PIN_COUNT_LOW) { *flags |= CKF_USER_PIN_FINAL_TRY; *flags &= ~(CKF_USER_PIN_COUNT_LOW); } else { *flags |= CKF_USER_PIN_COUNT_LOW; } } else { if (*flags & CKF_SO_PIN_FINAL_TRY) { *flags |= CKF_SO_PIN_LOCKED; *flags &= ~(CKF_SO_PIN_FINAL_TRY); } else if (*flags & CKF_SO_PIN_COUNT_LOW) { *flags |= CKF_SO_PIN_FINAL_TRY; *flags &= ~(CKF_SO_PIN_COUNT_LOW); } else { *flags |= CKF_SO_PIN_COUNT_LOW; } } } /* * The Initial Developer of the Original Code is International * Business Machines Corporation. Portions created by IBM * Corporation are Copyright (C) 2005 International Business * Machines Corporation. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the Common Public License as published by * IBM Corporation; either version 1 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * Common Public License for more details. * * You should have received a copy of the Common Public License * along with this program; if not, a copy can be viewed at * http://www.opensource.org/licenses/cpl1.0.php. */ /* (C) COPYRIGHT International Business Machines Corp. 2001, 2002, 2005 */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include "tpmtok_int.h" CK_RV sign_mgr_init(SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_MECHANISM * mech, CK_BBOOL recover_mode, CK_OBJECT_HANDLE key) { OBJECT * key_obj = NULL; CK_ATTRIBUTE * attr = NULL; CK_BYTE * ptr = NULL; CK_KEY_TYPE keytype; CK_OBJECT_CLASS class; CK_BBOOL flag; CK_RV rc; if (! sess || ! ctx) { return (CKR_FUNCTION_FAILED); } if (ctx->active != FALSE) { return (CKR_OPERATION_ACTIVE); } rc = object_mgr_find_in_map1(sess->hContext, key, &key_obj); if (rc != CKR_OK) { return (CKR_KEY_HANDLE_INVALID); } rc = template_attribute_find(key_obj->template, CKA_SIGN, &attr); if (rc == FALSE) { return (CKR_KEY_TYPE_INCONSISTENT); } else { flag = *(CK_BBOOL *)attr->pValue; if (flag != TRUE) { return (CKR_KEY_FUNCTION_NOT_PERMITTED); } } switch (mech->mechanism) { case CKM_RSA_PKCS: { rc = template_attribute_find(key_obj->template, CKA_KEY_TYPE, &attr); if (rc == FALSE) { return (CKR_KEY_TYPE_INCONSISTENT); } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_RSA) { return (CKR_KEY_TYPE_INCONSISTENT); } } // must be a PRIVATE key // flag = template_attribute_find(key_obj->template, CKA_CLASS, &attr); if (flag == FALSE) { return (CKR_KEY_TYPE_INCONSISTENT); } else class = *(CK_OBJECT_CLASS *)attr->pValue; if (class != CKO_PRIVATE_KEY) { return (CKR_KEY_TYPE_INCONSISTENT); } // PKCS #11 doesn't allow multi - part RSA operations // ctx->context_len = 0; ctx->context = NULL; } break; case CKM_MD5_RSA_PKCS: case CKM_SHA1_RSA_PKCS: { rc = template_attribute_find(key_obj->template, CKA_KEY_TYPE, &attr); if (rc == FALSE) { return (CKR_KEY_TYPE_INCONSISTENT); } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_RSA) { return (CKR_KEY_TYPE_INCONSISTENT); } } // must be a PRIVATE key operation // flag = template_attribute_find(key_obj->template, CKA_CLASS, &attr); if (flag == FALSE) { return (CKR_FUNCTION_FAILED); } else class = *(CK_OBJECT_CLASS *)attr->pValue; if (class != CKO_PRIVATE_KEY) { return (CKR_FUNCTION_FAILED); } ctx->context_len = sizeof (RSA_DIGEST_CONTEXT); ctx->context = (CK_BYTE *)malloc( sizeof (RSA_DIGEST_CONTEXT)); if (! ctx->context) { return (CKR_HOST_MEMORY); } (void) memset(ctx->context, 0x0, sizeof (RSA_DIGEST_CONTEXT)); } break; case CKM_MD5_HMAC: case CKM_SHA_1_HMAC: { if (mech->ulParameterLen != 0) { return (CKR_MECHANISM_PARAM_INVALID); } rc = template_attribute_find(key_obj->template, CKA_KEY_TYPE, &attr); if (rc == FALSE) { return (CKR_KEY_TYPE_INCONSISTENT); } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_GENERIC_SECRET) { return (CKR_KEY_TYPE_INCONSISTENT); } } // PKCS #11 doesn't allow multi - part HMAC operations // ctx->context_len = 0; ctx->context = NULL; } break; case CKM_MD5_HMAC_GENERAL: case CKM_SHA_1_HMAC_GENERAL: { CK_MAC_GENERAL_PARAMS *param = (CK_MAC_GENERAL_PARAMS *)mech->pParameter; if (mech->ulParameterLen != sizeof (CK_MAC_GENERAL_PARAMS)) { return (CKR_MECHANISM_PARAM_INVALID); } if ((mech->mechanism == CKM_MD5_HMAC_GENERAL) && (*param > 16)) { return (CKR_MECHANISM_PARAM_INVALID); } if ((mech->mechanism == CKM_SHA_1_HMAC_GENERAL) && (*param > 20)) { return (CKR_MECHANISM_PARAM_INVALID); } rc = template_attribute_find(key_obj->template, CKA_KEY_TYPE, &attr); if (rc == FALSE) { return (CKR_KEY_TYPE_INCONSISTENT); } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_GENERIC_SECRET) { return (CKR_KEY_TYPE_INCONSISTENT); } } // PKCS #11 doesn't allow multi - part HMAC operations // ctx->context_len = 0; ctx->context = NULL; } break; default: return (CKR_MECHANISM_INVALID); } if (mech->ulParameterLen > 0 && mech->pParameter == NULL) return (CKR_ARGUMENTS_BAD); if (mech->ulParameterLen > 0) { ptr = (CK_BYTE *)malloc(mech->ulParameterLen); if (! ptr) { return (CKR_HOST_MEMORY); } (void) memcpy(ptr, mech->pParameter, mech->ulParameterLen); } ctx->key = key; ctx->mech.ulParameterLen = mech->ulParameterLen; ctx->mech.mechanism = mech->mechanism; ctx->mech.pParameter = ptr; ctx->multi = FALSE; ctx->active = TRUE; ctx->recover = recover_mode; return (CKR_OK); } CK_RV sign_mgr_cleanup(SIGN_VERIFY_CONTEXT *ctx) { if (! ctx) { return (CKR_FUNCTION_FAILED); } ctx->key = 0; ctx->mech.ulParameterLen = 0; ctx->mech.mechanism = 0; ctx->multi = FALSE; ctx->active = FALSE; ctx->recover = FALSE; ctx->context_len = 0; if (ctx->mech.pParameter) { free(ctx->mech.pParameter); ctx->mech.pParameter = NULL; } if (ctx->context) { free(ctx->context); ctx->context = NULL; } return (CKR_OK); } CK_RV sign_mgr_sign(SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len) { if (! sess || ! ctx) { return (CKR_FUNCTION_FAILED); } if (ctx->active == FALSE) { return (CKR_OPERATION_NOT_INITIALIZED); } if (ctx->recover == TRUE) { return (CKR_OPERATION_NOT_INITIALIZED); } // if the caller just wants the signature length, there is no reason to // specify the input data. I just need the input data length // if ((length_only == FALSE) && (! in_data || ! out_data)) { return (CKR_FUNCTION_FAILED); } if (ctx->multi == TRUE) { return (CKR_OPERATION_ACTIVE); } switch (ctx->mech.mechanism) { case CKM_RSA_PKCS: return (rsa_pkcs_sign(sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len)); case CKM_MD5_RSA_PKCS: case CKM_SHA1_RSA_PKCS: return (rsa_hash_pkcs_sign(sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len)); case CKM_MD5_HMAC: case CKM_MD5_HMAC_GENERAL: return (md5_hmac_sign(sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len)); case CKM_SHA_1_HMAC: case CKM_SHA_1_HMAC_GENERAL: return (sha1_hmac_sign(sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len)); default: return (CKR_MECHANISM_INVALID); } } CK_RV sign_mgr_sign_update(SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len) { if (! sess || ! ctx || ! in_data) { return (CKR_FUNCTION_FAILED); } if (ctx->active == FALSE) { return (CKR_OPERATION_NOT_INITIALIZED); } if (ctx->recover == TRUE) { return (CKR_OPERATION_NOT_INITIALIZED); } ctx->multi = TRUE; switch (ctx->mech.mechanism) { case CKM_MD5_RSA_PKCS: case CKM_SHA1_RSA_PKCS: return (rsa_hash_pkcs_sign_update(sess, ctx, in_data, in_data_len)); default: return (CKR_MECHANISM_INVALID); } } CK_RV sign_mgr_sign_final(SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * signature, CK_ULONG * sig_len) { if (! sess || ! ctx) { return (CKR_FUNCTION_FAILED); } if (ctx->active == FALSE) { return (CKR_OPERATION_NOT_INITIALIZED); } if (ctx->recover == TRUE) { return (CKR_OPERATION_NOT_INITIALIZED); } switch (ctx->mech.mechanism) { case CKM_MD5_RSA_PKCS: case CKM_SHA1_RSA_PKCS: return (rsa_hash_pkcs_sign_final(sess, length_only, ctx, signature, sig_len)); default: return (CKR_MECHANISM_INVALID); } } CK_RV sign_mgr_sign_recover(SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len) { if (! sess || ! ctx) { return (CKR_FUNCTION_FAILED); } if (ctx->active == FALSE) { return (CKR_OPERATION_NOT_INITIALIZED); } if (ctx->recover == FALSE) { return (CKR_OPERATION_NOT_INITIALIZED); } // if the caller just wants the signature length, there is no reason to // specify the input data. I just need the input data length // if ((length_only == FALSE) && (! in_data || ! out_data)) { return (CKR_FUNCTION_FAILED); } if (ctx->multi == TRUE) { return (CKR_OPERATION_ACTIVE); } switch (ctx->mech.mechanism) { case CKM_RSA_PKCS: return (rsa_pkcs_sign(sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len)); default: return (CKR_MECHANISM_INVALID); } } /* * Common Public License Version 0.5 * * THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF * THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, * REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES * RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. * * 1. DEFINITIONS * * "Contribution" means: * a) in the case of the initial Contributor, the * initial code and documentation distributed under * this Agreement, and * * b) in the case of each subsequent Contributor: * i) changes to the Program, and * ii) additions to the Program; * * where such changes and/or additions to the Program * originate from and are distributed by that * particular Contributor. A Contribution 'originates' * from a Contributor if it was added to the Program * by such Contributor itself or anyone acting on such * Contributor's behalf. Contributions do not include * additions to the Program which: (i) are separate * modules of software distributed in conjunction with * the Program under their own license agreement, and * (ii) are not derivative works of the Program. * * * "Contributor" means any person or entity that distributes * the Program. * * "Licensed Patents " mean patent claims licensable by a * Contributor which are necessarily infringed by the use or * sale of its Contribution alone or when combined with the * Program. * * "Program" means the Contributions distributed in * accordance with this Agreement. * * "Recipient" means anyone who receives the Program under * this Agreement, including all Contributors. * * 2. GRANT OF RIGHTS * * a) Subject to the terms of this Agreement, each * Contributor hereby grants Recipient a * no - exclusive, worldwide, royalt - free copyright * license to reproduce, prepare derivative works of, * publicly display, publicly perform, distribute and * sublicense the Contribution of such Contributor, if * any, and such derivative works, in source code and * object code form. * * b) Subject to the terms of this Agreement, each * Contributor hereby grants Recipient a * no - exclusive, worldwide, royalt - free patent * license under Licensed Patents to make, use, sell, * offer to sell, import and otherwise transfer the * Contribution of such Contributor, if any, in source * code and object code form. This patent license * shall apply to the combination of the Contribution * and the Program if, at the time the Contribution is * added by the Contributor, such addition of the * Contribution causes such combination to be covered * by the Licensed Patents. The patent license shall * not apply to any other combinations which include * the Contribution. No hardware per se is licensed * hereunder. * * c) Recipient understands that although each * Contributor grants the licenses to its * Contributions set forth herein, no assurances are * provided by any Contributor that the Program does * not infringe the patent or other intellectual * property rights of any other entity. Each * Contributor disclaims any liability to Recipient * for claims brought by any other entity based on * infringement of intellectual property rights or * otherwise. As a condition to exercising the rights * and licenses granted hereunder, each Recipient * hereby assumes sole responsibility to secure any * other intellectual property rights needed, if any. * * For example, if a third party patent license is * required to allow Recipient to distribute the * Program, it is Recipient's responsibility to * acquire that license before distributing the * Program. * * d) Each Contributor represents that to its * knowledge it has sufficient copyright rights in its * Contribution, if any, to grant the copyright * license set forth in this Agreement. * * 3. REQUIREMENTS * * A Contributor may choose to distribute the Program in * object code form under its own license agreement, provided * that: * a) it complies with the terms and conditions of * this Agreement; and * * b) its license agreement: * i) effectively disclaims on behalf of all * Contributors all warranties and conditions, express * and implied, including warranties or conditions of * title and no - infringement, and implied warranties * or conditions of merchantability and fitness for a * particular purpose; * * ii) effectively excludes on behalf of all * Contributors all liability for damages, including * direct, indirect, special, incidental and * consequential damages, such as lost profits; * * iii) states that any provisions which differ from * this Agreement are offered by that Contributor * alone and not by any other party; and * * iv) states that source code for the Program is * available from such Contributor, and informs * licensees how to obtain it in a reasonable manner * on or through a medium customarily used for * software exchange. * * When the Program is made available in source code form: * a) it must be made available under this Agreement; * and * b) a copy of this Agreement must be included with * each copy of the Program. * * Contributors may not remove or alter any copyright notices * contained within the Program. * * Each Contributor must identify itself as the originator of * its Contribution, if any, in a manner that reasonably * allows subsequent Recipients to identify the originator of * the Contribution. * * * 4. COMMERCIAL DISTRIBUTION * * Commercial distributors of software may accept certain * responsibilities with respect to end users, business * partners and the like. While this license is intended to * facilitate the commercial use of the Program, the * Contributor who includes the Program in a commercial * product offering should do so in a manner which does not * create potential liability for other Contributors. * Therefore, if a Contributor includes the Program in a * commercial product offering, such Contributor ("Commercial * Contributor") hereby agrees to defend and indemnify every * other Contributor ("Indemnified Contributor") against any * losses, damages and costs (collectively "Losses") arising * from claims, lawsuits and other legal actions brought by a * third party against the Indemnified Contributor to the * extent caused by the acts or omissions of such Commercial * Contributor in connection with its distribution of the * Program in a commercial product offering. The obligations * in this section do not apply to any claims or Losses * relating to any actual or alleged intellectual property * infringement. In order to qualify, an Indemnified * Contributor must: a) promptly notify the Commercial * Contributor in writing of such claim, and b) allow the * Commercial Contributor to control, and cooperate with the * Commercial Contributor in, the defense and any related * settlement negotiations. The Indemnified Contributor may * participate in any such claim at its own expense. * * * For example, a Contributor might include the Program in a * commercial product offering, Product X. That Contributor * is then a Commercial Contributor. If that Commercial * Contributor then makes performance claims, or offers * warranties related to Product X, those performance claims * and warranties are such Commercial Contributor's * responsibility alone. Under this section, the Commercial * Contributor would have to defend claims against the other * Contributors related to those performance claims and * warranties, and if a court requires any other Contributor * to pay any damages as a result, the Commercial Contributor * must pay those damages. * * * 5. NO WARRANTY * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE * PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR * IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR * CONDITIONS OF TITLE, NO - INFRINGEMENT, MERCHANTABILITY OR * FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely * responsible for determining the appropriateness of using * and distributing the Program and assumes all risks * associated with its exercise of rights under this * Agreement, including but not limited to the risks and * costs of program errors, compliance with applicable laws, * damage to or loss of data, programs or equipment, and * unavailability or interruption of operations. * * 6. DISCLAIMER OF LIABILITY * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER * RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION * LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE * OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * 7. GENERAL * * If any provision of this Agreement is invalid or * unenforceable under applicable law, it shall not affect * the validity or enforceability of the remainder of the * terms of this Agreement, and without further action by the * parties hereto, such provision shall be reformed to the * minimum extent necessary to make such provision valid and * enforceable. * * * If Recipient institutes patent litigation against a * Contributor with respect to a patent applicable to * software (including a cros - claim or counterclaim in a * lawsuit), then any patent licenses granted by that * Contributor to such Recipient under this Agreement shall * terminate as of the date such litigation is filed. In * addition, If Recipient institutes patent litigation * against any entity (including a cros - claim or * counterclaim in a lawsuit) alleging that the Program * itself (excluding combinations of the Program with other * software or hardware) infringes such Recipient's * patent(s), then such Recipient's rights granted under * Section 2(b) shall terminate as of the date such * litigation is filed. * * All Recipient's rights under this Agreement shall * terminate if it fails to comply with any of the material * terms or conditions of this Agreement and does not cure * such failure in a reasonable period of time after becoming * aware of such noncompliance. If all Recipient's rights * under this Agreement terminate, Recipient agrees to cease * use and distribution of the Program as soon as reasonably * practicable. However, Recipient's obligations under this * Agreement and any licenses granted by Recipient relating * to the Program shall continue and survive. * * Everyone is permitted to copy and distribute copies of * this Agreement, but in order to avoid inconsistency the * Agreement is copyrighted and may only be modified in the * following manner. The Agreement Steward reserves the right * to publish new versions (including revisions) of this * Agreement from time to time. No one other than the * Agreement Steward has the right to modify this Agreement. * * IBM is the initial Agreement Steward. IBM may assign the * responsibility to serve as the Agreement Steward to a * suitable separate entity. Each new version of the * Agreement will be given a distinguishing version number. * The Program (including Contributions) may always be * distributed subject to the version of the Agreement under * which it was received. In addition, after a new version of * the Agreement is published, Contributor may elect to * distribute the Program (including its Contributions) under * the new version. Except as expressly stated in Sections * 2(a) and 2(b) above, Recipient receives no rights or * licenses to the intellectual property of any Contributor * under this Agreement, whether expressly, by implication, * estoppel or otherwise. All rights in the Program not * expressly granted under this Agreement are reserved. * * * This Agreement is governed by the laws of the State of New * York and the intellectual property laws of the United * States of America. No party to this Agreement will bring a * legal action under this Agreement more than one year after * the cause of action arose. Each party waives its rights to * a jury trial in any resulting litigation. * * * * (C) COPYRIGHT International Business Machines Corp. 2001, 2002 */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include "tpmtok_int.h" // template_add_attributes() // // blindly add the given attributes to the template. do no sanity checking // at this point. sanity checking will occur later. // CK_RV template_add_attributes(TEMPLATE * tmpl, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount) { CK_ATTRIBUTE * attr = NULL; CK_RV rc; unsigned int i; for (i = 0; i < ulCount; i++) { if (! is_attribute_defined(pTemplate[i].type)) { return (CKR_ATTRIBUTE_TYPE_INVALID); } attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + pTemplate[i].ulValueLen); if (! attr) { return (CKR_HOST_MEMORY); } attr->type = pTemplate[i].type; attr->ulValueLen = pTemplate[i].ulValueLen; if (attr->ulValueLen != 0) { attr->pValue = (CK_BYTE *)attr + sizeof (CK_ATTRIBUTE); (void) memcpy(attr->pValue, pTemplate[i].pValue, attr->ulValueLen); } else attr->pValue = NULL; rc = template_update_attribute(tmpl, attr); if (rc != CKR_OK) { free(attr); return (rc); } } return (CKR_OK); } // template_add_default_attributes() // CK_RV template_add_default_attributes(TEMPLATE * tmpl, CK_ULONG class, CK_ULONG subclass, CK_ULONG mode) { CK_RV rc; // first add the default common attributes // rc = template_set_default_common_attributes(tmpl); if (rc != CKR_OK) { return (rc); } // set the template class - specific default attributes // switch (class) { case CKO_DATA: return (data_object_set_default_attributes(tmpl, mode)); case CKO_CERTIFICATE: if (subclass == CKC_X_509) return (cert_x509_set_default_attributes(tmpl, mode)); else return (CKR_OK); case CKO_PUBLIC_KEY: switch (subclass) { case CKK_RSA: return (rsa_publ_set_default_attributes( tmpl, mode)); default: return (CKR_ATTRIBUTE_VALUE_INVALID); } case CKO_PRIVATE_KEY: switch (subclass) { case CKK_RSA: return (rsa_priv_set_default_attributes( tmpl, mode)); default: return (CKR_ATTRIBUTE_VALUE_INVALID); } case CKO_SECRET_KEY: switch (subclass) { case CKK_GENERIC_SECRET: return (generic_secret_set_default_attributes( tmpl, mode)); default: return (CKR_ATTRIBUTE_VALUE_INVALID); } case CKO_HW_FEATURE: switch (subclass) { case CKH_CLOCK: return (clock_set_default_attributes( tmpl)); case CKH_MONOTONIC_COUNTER: return (counter_set_default_attributes( tmpl)); default: return (CKR_ATTRIBUTE_VALUE_INVALID); } case CKO_DOMAIN_PARAMETERS: switch (subclass) { default: return (CKR_ATTRIBUTE_VALUE_INVALID); } default: return (CKR_ATTRIBUTE_VALUE_INVALID); } } // template_attribute_find() // // find the attribute in the list and return (its value // CK_BBOOL template_attribute_find(TEMPLATE * tmpl, CK_ATTRIBUTE_TYPE type, CK_ATTRIBUTE ** attr) { DL_NODE * node = NULL; CK_ATTRIBUTE * a = NULL; if (! tmpl || ! attr) return (FALSE); node = tmpl->attribute_list; while (node != NULL) { a = (CK_ATTRIBUTE *)node->data; if (type == a->type) { *attr = a; return (TRUE); } node = node->next; } *attr = NULL; return (FALSE); } // template_attribute_find_multiple() // // find the attributes in the list and return (their values // void template_attribute_find_multiple(TEMPLATE * tmpl, ATTRIBUTE_PARSE_LIST * parselist, CK_ULONG plcount) { CK_ATTRIBUTE * attr = NULL; CK_ULONG i; for (i = 0; i < plcount; i++) { parselist[i].found = template_attribute_find( tmpl, parselist[i].type, &attr); if (parselist[i].found && parselist[i].ptr != NULL) (void) memcpy(parselist[i].ptr, attr->pValue, parselist[i].len); } } CK_RV template_check_required_attributes(TEMPLATE * tmpl, CK_ULONG class, CK_ULONG subclass, CK_ULONG mode) { if (class == CKO_DATA) return (data_object_check_required_attributes( tmpl, mode)); else if (class == CKO_CERTIFICATE) { if (subclass == CKC_X_509) return (cert_x509_check_required_attributes( tmpl, mode)); else return (cert_vendor_check_required_attributes( tmpl, mode)); } else if (class == CKO_PUBLIC_KEY) { switch (subclass) { case CKK_RSA: return (rsa_publ_check_required_attributes( tmpl, mode)); default: return (CKR_ATTRIBUTE_VALUE_INVALID); } } else if (class == CKO_PRIVATE_KEY) { switch (subclass) { case CKK_RSA: return (rsa_priv_check_required_attributes( tmpl, mode)); default: return (CKR_ATTRIBUTE_VALUE_INVALID); } } else if (class == CKO_SECRET_KEY) { switch (subclass) { case CKK_GENERIC_SECRET: return ( generic_secret_check_required_attributes( tmpl, mode)); default: return (CKR_ATTRIBUTE_VALUE_INVALID); } } else if (class == CKO_HW_FEATURE) { switch (subclass) { case CKH_CLOCK: return ( clock_check_required_attributes( tmpl, mode)); case CKH_MONOTONIC_COUNTER: return ( counter_check_required_attributes( tmpl, mode)); default: return (CKR_ATTRIBUTE_VALUE_INVALID); } } else if (class == CKO_DOMAIN_PARAMETERS) { switch (subclass) { default: return (CKR_ATTRIBUTE_VALUE_INVALID); } } return (CKR_ATTRIBUTE_VALUE_INVALID); } // template_check_required_base_attributes() // // check to make sure that attributes required by Cryptoki are // present. does not check to see if the attribute makes sense // for the particular object (that is done in the 'validate' routines) // CK_RV template_check_required_base_attributes(TEMPLATE * tmpl, CK_ULONG mode) { CK_ATTRIBUTE * attr; CK_BBOOL found; found = template_attribute_find(tmpl, CKA_CLASS, &attr); if (mode == MODE_CREATE && found == FALSE) return (CKR_TEMPLATE_INCOMPLETE); return (CKR_OK); } // template_compare() // CK_BBOOL template_compare(CK_ATTRIBUTE * t1, CK_ULONG ulCount, TEMPLATE * t2) { CK_ATTRIBUTE * attr1 = NULL; CK_ATTRIBUTE * attr2 = NULL; CK_ULONG i; CK_RV rc; if (! t1 || ! t2) return (FALSE); attr1 = t1; for (i = 0; i < ulCount; i++) { rc = template_attribute_find(t2, attr1->type, &attr2); if (rc == FALSE) return (FALSE); if (attr1->ulValueLen != attr2->ulValueLen) return (FALSE); if (memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen) != 0) return (FALSE); attr1++; } return (TRUE); } // template_copy() // // This doesn't copy the template items verbatim. The new template is in // the reverse order of the old one. This should not have any effect. // // This is very similar to template_merge(). template_merge() can also // be used to copy a list (of unique attributes) but is slower because for // each attribute, it must search through the list. // CK_RV template_copy(TEMPLATE *dest, TEMPLATE *src) { DL_NODE *node; if (! dest || ! src) { return (CKR_FUNCTION_FAILED); } node = src->attribute_list; while (node) { CK_ATTRIBUTE *attr = (CK_ATTRIBUTE *)node->data; CK_ATTRIBUTE *new_attr = NULL; CK_ULONG len; len = sizeof (CK_ATTRIBUTE) + attr->ulValueLen; new_attr = (CK_ATTRIBUTE *)malloc(len); if (! new_attr) { return (CKR_HOST_MEMORY); } (void) memcpy(new_attr, attr, len); new_attr->pValue = (CK_BYTE *)new_attr + sizeof (CK_ATTRIBUTE); dest->attribute_list = dlist_add_as_first(dest->attribute_list, new_attr); node = node->next; } return (CKR_OK); } // template_flatten() - this still gets used when saving token objects to disk // CK_RV template_flatten(TEMPLATE * tmpl, CK_BYTE * dest) { DL_NODE * node = NULL; CK_BYTE * ptr = NULL; CK_ULONG_32 long_len; CK_ATTRIBUTE_32 *attr_32; CK_ULONG Val; CK_ULONG_32 Val_32; CK_ULONG * pVal; long_len = sizeof (CK_ULONG); if (! tmpl || ! dest) { return (CKR_FUNCTION_FAILED); } ptr = dest; node = tmpl->attribute_list; while (node) { CK_ATTRIBUTE *attr = (CK_ATTRIBUTE *)node->data; if (long_len == 4) { (void) memcpy(ptr, attr, sizeof (CK_ATTRIBUTE) + attr->ulValueLen); ptr += sizeof (CK_ATTRIBUTE) + attr->ulValueLen; } else { attr_32 = malloc(sizeof (CK_ATTRIBUTE_32)); if (! attr_32) { return (CKR_HOST_MEMORY); } attr_32->type = attr->type; attr_32->pValue = 0x00; if ((attr->type == CKA_CLASS || attr->type == CKA_KEY_TYPE || attr->type == CKA_MODULUS_BITS || attr->type == CKA_VALUE_BITS || attr->type == CKA_CERTIFICATE_TYPE || attr->type == CKA_VALUE_LEN) && attr->ulValueLen != 0) { attr_32->ulValueLen = sizeof (CK_ULONG_32); (void) memcpy(ptr, attr_32, sizeof (CK_ATTRIBUTE_32)); ptr += sizeof (CK_ATTRIBUTE_32); pVal = (CK_ULONG *)attr->pValue; Val = *pVal; Val_32 = (CK_ULONG_32)Val; (void) memcpy(ptr, &Val_32, sizeof (CK_ULONG_32)); ptr += sizeof (CK_ULONG_32); } else { attr_32->ulValueLen = attr->ulValueLen; (void) memcpy(ptr, attr_32, sizeof (CK_ATTRIBUTE_32)); ptr += sizeof (CK_ATTRIBUTE_32); if (attr->ulValueLen != 0) { (void) memcpy(ptr, attr->pValue, attr->ulValueLen); ptr += attr->ulValueLen; } } free(attr_32); } node = node->next; } return (CKR_OK); } CK_RV template_unflatten(TEMPLATE ** new_tmpl, CK_BYTE * buf, CK_ULONG count) { TEMPLATE * tmpl = NULL; CK_ATTRIBUTE * a2 = NULL; CK_BYTE *ptr = NULL; CK_ULONG i, len; CK_RV rc; CK_ULONG_32 long_len = sizeof (CK_ULONG); CK_ULONG_32 attr_ulong_32; CK_ULONG attr_ulong; CK_ATTRIBUTE * a1_64 = NULL; CK_ATTRIBUTE_32 * a1 = NULL; if (! new_tmpl || ! buf) { return (CKR_FUNCTION_FAILED); } tmpl = (TEMPLATE *)malloc(sizeof (TEMPLATE)); if (! tmpl) { return (CKR_HOST_MEMORY); } (void) memset(tmpl, 0x0, sizeof (TEMPLATE)); ptr = buf; for (i = 0; i < count; i++) { if (long_len == 4) { void *aptr = ptr; a1_64 = (CK_ATTRIBUTE *)aptr; len = sizeof (CK_ATTRIBUTE) + a1_64->ulValueLen; a2 = (CK_ATTRIBUTE *)malloc(len); if (! a2) { (void) template_free(tmpl); return (CKR_HOST_MEMORY); } (void) memcpy(a2, a1_64, len); } else { void *aptr = ptr; a1 = (CK_ATTRIBUTE_32 *)aptr; if ((a1->type == CKA_CLASS || a1->type == CKA_KEY_TYPE || a1->type == CKA_MODULUS_BITS || a1->type == CKA_VALUE_BITS || a1->type == CKA_CERTIFICATE_TYPE || a1->type == CKA_VALUE_LEN) && a1->ulValueLen != 0) { len = sizeof (CK_ATTRIBUTE) + sizeof (CK_ULONG); } else { len = sizeof (CK_ATTRIBUTE) + a1->ulValueLen; } a2 = (CK_ATTRIBUTE *)malloc(len); if (! a2) { return (CKR_HOST_MEMORY); } a2->type = a1->type; if ((a1->type == CKA_CLASS || a1->type == CKA_KEY_TYPE || a1->type == CKA_MODULUS_BITS || a1->type == CKA_VALUE_BITS || a1->type == CKA_CERTIFICATE_TYPE || a1->type == CKA_VALUE_LEN) && a1->ulValueLen != 0) { a2->ulValueLen = sizeof (CK_ULONG); { CK_ULONG_32 *p32; CK_BYTE *pb2; void *aptr = a1; void *bptr; pb2 = (CK_BYTE *)aptr; pb2 += sizeof (CK_ATTRIBUTE_32); bptr = pb2; p32 = (CK_ULONG_32 *)bptr; attr_ulong_32 = *p32; } attr_ulong = attr_ulong_32; { CK_BYTE *pb2; pb2 = (CK_BYTE *)a2; pb2 += sizeof (CK_ATTRIBUTE); (void) memcpy(pb2, (CK_BYTE *)&attr_ulong, sizeof (CK_ULONG)); } } else { CK_BYTE *pb2, *pb; a2->ulValueLen = a1->ulValueLen; pb2 = (CK_BYTE *)a2; pb2 += sizeof (CK_ATTRIBUTE); pb = (CK_BYTE *)a1; pb += sizeof (CK_ATTRIBUTE_32); (void) memcpy(pb2, pb, a1->ulValueLen); } } if (a2->ulValueLen != 0) a2->pValue = (CK_BYTE *)a2 + sizeof (CK_ATTRIBUTE); else a2->pValue = NULL; rc = template_update_attribute(tmpl, a2); if (rc != CKR_OK) { free(a2); (void) template_free(tmpl); return (rc); } if (long_len == 4) ptr += len; else ptr += sizeof (CK_ATTRIBUTE_32) + a1->ulValueLen; } *new_tmpl = tmpl; return (CKR_OK); } CK_RV template_free(TEMPLATE *tmpl) { if (! tmpl) return (CKR_OK); while (tmpl->attribute_list) { CK_ATTRIBUTE *attr = (CK_ATTRIBUTE *)tmpl->attribute_list->data; if (attr) free(attr); tmpl->attribute_list = dlist_remove_node(tmpl->attribute_list, tmpl->attribute_list); } free(tmpl); return (CKR_OK); } CK_BBOOL template_get_class(TEMPLATE * tmpl, CK_ULONG * class, CK_ULONG * subclass) { DL_NODE * node; CK_BBOOL found; if (! tmpl || ! class || ! subclass) return (FALSE); node = tmpl->attribute_list; while (node) { CK_ATTRIBUTE *attr = (CK_ATTRIBUTE *)node->data; if (attr->type == CKA_CLASS) { *class = *(CK_OBJECT_CLASS *)attr->pValue; found = TRUE; } if (attr->type == CKA_CERTIFICATE_TYPE) *subclass = *(CK_CERTIFICATE_TYPE *)attr->pValue; if (attr->type == CKA_KEY_TYPE) *subclass = *(CK_KEY_TYPE *)attr->pValue; node = node->next; } return (found); } CK_ULONG template_get_count(TEMPLATE *tmpl) { if (tmpl == NULL) return (0); return (dlist_length(tmpl->attribute_list)); } CK_ULONG template_get_size(TEMPLATE *tmpl) { DL_NODE * node; CK_ULONG size = 0; if (tmpl == NULL) return (0); node = tmpl->attribute_list; while (node) { CK_ATTRIBUTE *attr = (CK_ATTRIBUTE *)node->data; size += sizeof (CK_ATTRIBUTE) + attr->ulValueLen; node = node->next; } return (size); } CK_ULONG template_get_compressed_size(TEMPLATE *tmpl) { DL_NODE * node; CK_ULONG size = 0; if (tmpl == NULL) return (0); node = tmpl->attribute_list; while (node) { CK_ATTRIBUTE *attr = (CK_ATTRIBUTE *)node->data; size += sizeof (CK_ATTRIBUTE_32); if ((attr->type == CKA_CLASS || attr->type == CKA_KEY_TYPE || attr->type == CKA_MODULUS_BITS || attr->type == CKA_VALUE_BITS || attr->type == CKA_CERTIFICATE_TYPE || attr->type == CKA_VALUE_LEN) && attr->ulValueLen != 0) { size += sizeof (CK_ULONG_32); } else { size += attr->ulValueLen; } node = node->next; } return (size); } /* * template_is_okay_to_reveal_attribute() * * determines whether the specified CK_ATTRIBUTE_TYPE is allowed to * be leave the card in the clear. note: the specified template doesn't need * to actually posess an attribute of type 'type'. The template is * provided mainly to determine the object class and subclass * * this routine is called by C_GetAttributeValue which exports the attributes * in the clear. this routine is NOT called when wrapping a key. */ CK_BBOOL template_check_exportability(TEMPLATE *tmpl, CK_ATTRIBUTE_TYPE type) { CK_ATTRIBUTE * attr = NULL; CK_ULONG class; CK_ULONG subclass; CK_BBOOL val; if (! tmpl) return (FALSE); (void) template_get_class(tmpl, &class, &subclass); if (class != CKO_PRIVATE_KEY && class != CKO_SECRET_KEY) return (TRUE); val = template_attribute_find(tmpl, CKA_SENSITIVE, &attr); if (val) { val = *(CK_BBOOL *)attr->pValue; if (val == FALSE) return (TRUE); } else { return (FALSE); } if (class == CKO_PRIVATE_KEY) { switch (subclass) { case CKK_RSA: return (rsa_priv_check_exportability(type)); default: return (CKR_ATTRIBUTE_VALUE_INVALID); } } else if (class == CKO_SECRET_KEY) { return (secret_key_check_exportability(type)); } return (CKR_ATTRIBUTE_VALUE_INVALID); } CK_RV template_merge(TEMPLATE *dest, TEMPLATE **src) { DL_NODE *node; CK_RV rc; if (! dest || ! src) { return (CKR_FUNCTION_FAILED); } node = (*src)->attribute_list; while (node) { CK_ATTRIBUTE *attr = (CK_ATTRIBUTE *)node->data; rc = template_update_attribute(dest, attr); if (rc != CKR_OK) { return (rc); } node->data = NULL; node = node->next; } (void) template_free(*src); *src = NULL; return (CKR_OK); } /* * template_set_default_common_attributes() * * Set the default attributes common to all objects: * * CKA_TOKEN : FALSE * CKA_PRIVATE : TRUE -- Cryptoki leaves this up to the token to decide * CKA_MODIFIABLE : TRUE * CKA_LABEL : empty string */ CK_RV template_set_default_common_attributes(TEMPLATE *tmpl) { CK_ATTRIBUTE * token_attr; CK_ATTRIBUTE * priv_attr; CK_ATTRIBUTE * mod_attr; CK_ATTRIBUTE * label_attr; token_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + sizeof (CK_BBOOL)); priv_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + sizeof (CK_BBOOL)); mod_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + sizeof (CK_BBOOL)); label_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + 0); if (! token_attr || ! priv_attr || ! mod_attr || ! label_attr) { if (token_attr) free(token_attr); if (priv_attr) free(priv_attr); if (mod_attr) free(mod_attr); if (label_attr) free(label_attr); return (CKR_HOST_MEMORY); } token_attr->type = CKA_TOKEN; token_attr->ulValueLen = sizeof (CK_BBOOL); token_attr->pValue = (CK_BYTE *)token_attr + sizeof (CK_ATTRIBUTE); *(CK_BBOOL *)token_attr->pValue = FALSE; priv_attr->type = CKA_PRIVATE; priv_attr->ulValueLen = sizeof (CK_BBOOL); priv_attr->pValue = (CK_BYTE *)priv_attr + sizeof (CK_ATTRIBUTE); *(CK_BBOOL *)priv_attr->pValue = FALSE; mod_attr->type = CKA_MODIFIABLE; mod_attr->ulValueLen = sizeof (CK_BBOOL); mod_attr->pValue = (CK_BYTE *)mod_attr + sizeof (CK_ATTRIBUTE); *(CK_BBOOL *)mod_attr->pValue = TRUE; label_attr->type = CKA_LABEL; label_attr->ulValueLen = 0; // empty string label_attr->pValue = NULL; (void) template_update_attribute(tmpl, token_attr); (void) template_update_attribute(tmpl, priv_attr); (void) template_update_attribute(tmpl, mod_attr); (void) template_update_attribute(tmpl, label_attr); return (CKR_OK); } CK_RV template_update_attribute(TEMPLATE *tmpl, CK_ATTRIBUTE *new_attr) { DL_NODE * node = NULL; CK_ATTRIBUTE * attr = NULL; if (! tmpl || ! new_attr) { return (CKR_FUNCTION_FAILED); } node = tmpl->attribute_list; while (node != NULL) { attr = (CK_ATTRIBUTE *)node->data; if (new_attr->type == attr->type) { free(attr); tmpl->attribute_list = dlist_remove_node( tmpl->attribute_list, node); break; } node = node->next; } tmpl->attribute_list = dlist_add_as_first( tmpl->attribute_list, new_attr); return (CKR_OK); } CK_RV template_validate_attribute(TEMPLATE * tmpl, CK_ATTRIBUTE * attr, CK_ULONG class, CK_ULONG subclass, CK_ULONG mode) { if (class == CKO_DATA) return (data_object_validate_attribute(tmpl, attr, mode)); else if (class == CKO_CERTIFICATE) { if (subclass == CKC_X_509) return (cert_x509_validate_attribute(tmpl, attr, mode)); else return (cert_vendor_validate_attribute(tmpl, attr, mode)); } else if (class == CKO_PUBLIC_KEY) { switch (subclass) { case CKK_RSA: return (rsa_publ_validate_attribute(tmpl, attr, mode)); default: return (CKR_ATTRIBUTE_VALUE_INVALID); } } else if (class == CKO_PRIVATE_KEY) { switch (subclass) { case CKK_RSA: return (rsa_priv_validate_attribute(tmpl, attr, mode)); default: return (CKR_ATTRIBUTE_VALUE_INVALID); } } else if (class == CKO_SECRET_KEY) { switch (subclass) { case CKK_GENERIC_SECRET: return (generic_secret_validate_attribute(tmpl, attr, mode)); default: return (CKR_ATTRIBUTE_VALUE_INVALID); } } else if (class == CKO_HW_FEATURE) { switch (subclass) { case CKH_CLOCK: return (clock_validate_attribute(tmpl, attr, mode)); case CKH_MONOTONIC_COUNTER: return (counter_validate_attribute(tmpl, attr, mode)); default: return (CKR_ATTRIBUTE_VALUE_INVALID); } } else if (class == CKO_DOMAIN_PARAMETERS) { switch (subclass) { default: return (CKR_ATTRIBUTE_VALUE_INVALID); } } return (CKR_ATTRIBUTE_VALUE_INVALID); } CK_RV template_validate_attributes(TEMPLATE * tmpl, CK_ULONG class, CK_ULONG subclass, CK_ULONG mode) { DL_NODE *node; CK_RV rc = CKR_OK; node = tmpl->attribute_list; while (node) { CK_ATTRIBUTE *attr = (CK_ATTRIBUTE *)node->data; rc = template_validate_attribute(tmpl, attr, class, subclass, mode); if (rc != CKR_OK) { return (rc); } node = node->next; } return (CKR_OK); } CK_RV template_validate_base_attribute(TEMPLATE * tmpl, CK_ATTRIBUTE * attr, CK_ULONG mode) { if (! tmpl || ! attr) { return (CKR_FUNCTION_FAILED); } switch (attr->type) { case CKA_CLASS: if ((mode & (MODE_CREATE | MODE_DERIVE | MODE_KEYGEN | MODE_UNWRAP)) != 0) return (CKR_OK); break; case CKA_TOKEN: if ((mode & (MODE_CREATE | MODE_COPY | MODE_DERIVE | MODE_KEYGEN | MODE_UNWRAP)) != 0) return (CKR_OK); break; case CKA_PRIVATE: if ((mode & (MODE_CREATE | MODE_COPY | MODE_DERIVE | MODE_KEYGEN | MODE_UNWRAP)) != 0) return (CKR_OK); break; case CKA_LABEL: return (CKR_OK); case CKA_MODIFIABLE: if ((mode & (MODE_CREATE | MODE_COPY | MODE_DERIVE | MODE_KEYGEN | MODE_UNWRAP)) != 0) return (CKR_OK); break; default: return (CKR_TEMPLATE_INCONSISTENT); } return (CKR_ATTRIBUTE_READ_ONLY); } /* * The Initial Developer of the Original Code is International * Business Machines Corporation. Portions created by IBM * Corporation are Copyright (C) 2005 International Business * Machines Corporation. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the Common Public License as published by * IBM Corporation; either version 1 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * Common Public License for more details. * * You should have received a copy of the Common Public License * along with this program; if not, a copy can be viewed at * http://www.opensource.org/licenses/cpl1.0.php. */ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * Copyright 2012 Milan Jurik. All rights reserved. * Copyright (c) 2016 by Delphix. All rights reserved. * Copyright 2018 Jason King */ #include #include #include #include #include #include #include #include #include #include /* For CRYPTO_BYTES2BITS */ #include #include #include #include #include #include #include #include #include #include #include "tpmtok_int.h" #include "tpmtok_defs.h" #define MAX_RSA_KEYLENGTH 512 extern void stlogit(char *fmt, ...); CK_RV token_rng(TSS_HCONTEXT, CK_BYTE *, CK_ULONG); int tok_slot2local(CK_SLOT_ID); CK_RV token_specific_session(CK_SLOT_ID); CK_RV token_specific_final(TSS_HCONTEXT); CK_RV token_specific_rsa_decrypt( TSS_HCONTEXT, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *, OBJECT *); CK_RV token_specific_rsa_encrypt( TSS_HCONTEXT, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *, OBJECT *); CK_RV token_specific_rsa_sign( TSS_HCONTEXT, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *, OBJECT *); CK_RV token_specific_rsa_verify(TSS_HCONTEXT, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG, OBJECT *); CK_RV token_specific_rsa_generate_keypair(TSS_HCONTEXT, TEMPLATE *, TEMPLATE *); CK_RV token_specific_sha_init(DIGEST_CONTEXT *); CK_RV token_specific_sha_update(DIGEST_CONTEXT *, CK_BYTE *, CK_ULONG); CK_RV token_specific_sha_final(DIGEST_CONTEXT *, CK_BYTE *, CK_ULONG *); CK_RV token_specific_login(TSS_HCONTEXT, CK_USER_TYPE, CK_CHAR_PTR, CK_ULONG); CK_RV token_specific_logout(TSS_HCONTEXT); CK_RV token_specific_init_pin(TSS_HCONTEXT, CK_CHAR_PTR, CK_ULONG); CK_RV token_specific_set_pin(ST_SESSION_HANDLE, CK_CHAR_PTR, CK_ULONG, CK_CHAR_PTR, CK_ULONG); CK_RV token_specific_verify_so_pin(TSS_HCONTEXT, CK_CHAR_PTR, CK_ULONG); static CK_RV token_specific_init(char *, CK_SLOT_ID, TSS_HCONTEXT *); struct token_specific_struct token_specific = { "TPM_Debug", &token_specific_init, NULL, &token_rng, &token_specific_session, &token_specific_final, &token_specific_rsa_decrypt, &token_specific_rsa_encrypt, &token_specific_rsa_sign, &token_specific_rsa_verify, &token_specific_rsa_generate_keypair, NULL, NULL, NULL, &token_specific_login, &token_specific_logout, &token_specific_init_pin, &token_specific_set_pin, &token_specific_verify_so_pin }; /* The context we'll use globally to connect to the TSP */ /* TSP key handles */ TSS_HKEY hPublicRootKey = NULL_HKEY; TSS_HKEY hPublicLeafKey = NULL_HKEY; TSS_HKEY hPrivateRootKey = NULL_HKEY; TSS_HKEY hPrivateLeafKey = NULL_HKEY; TSS_UUID publicRootKeyUUID; TSS_UUID publicLeafKeyUUID; TSS_UUID privateRootKeyUUID; TSS_UUID privateLeafKeyUUID; /* TSP policy handles */ TSS_HPOLICY hDefaultPolicy = NULL_HPOLICY; /* PKCS#11 key handles */ int not_initialized = 0; CK_BYTE current_user_pin_sha[SHA1_DIGEST_LENGTH]; CK_BYTE current_so_pin_sha[SHA1_DIGEST_LENGTH]; static TPM_CAP_VERSION_INFO tpmvinfo; static CK_RV verify_user_pin(TSS_HCONTEXT, CK_BYTE *); static TSS_RESULT tss_assign_secret_key_policy(TSS_HCONTEXT, TSS_FLAG, TSS_HKEY, CK_CHAR *); static TSS_RESULT set_legacy_key_params(TSS_HKEY); static void local_uuid_clear(TSS_UUID *uuid) { if (uuid == NULL) return; (void) memset(uuid, 0, sizeof (TSS_UUID)); } /* convert from TSS_UUID to uuid_t */ static void tss_uuid_convert_from(TSS_UUID *uu, uuid_t ptr) { uint_t tmp; uchar_t *out = ptr; tmp = ntohl(uu->ulTimeLow); out[3] = (uchar_t)tmp; tmp >>= 8; out[2] = (uchar_t)tmp; tmp >>= 8; out[1] = (uchar_t)tmp; tmp >>= 8; out[0] = (uchar_t)tmp; tmp = ntohs(uu->usTimeMid); out[5] = (uchar_t)tmp; tmp >>= 8; out[4] = (uchar_t)tmp; tmp = ntohs(uu->usTimeHigh); out[7] = (uchar_t)tmp; tmp >>= 8; out[6] = (uchar_t)tmp; tmp = uu->bClockSeqHigh; out[8] = (uchar_t)tmp; tmp = uu->bClockSeqLow; out[9] = (uchar_t)tmp; (void) memcpy(out+10, uu->rgbNode, 6); } /* convert from uuid_t to TSS_UUID */ static void tss_uuid_convert_to(TSS_UUID *uuid, uuid_t in) { uchar_t *ptr; uint32_t ltmp; uint16_t stmp; ptr = in; ltmp = *ptr++; ltmp = (ltmp << 8) | *ptr++; ltmp = (ltmp << 8) | *ptr++; ltmp = (ltmp << 8) | *ptr++; uuid->ulTimeLow = ntohl(ltmp); stmp = *ptr++; stmp = (stmp << 8) | *ptr++; uuid->usTimeMid = ntohs(stmp); stmp = *ptr++; stmp = (stmp << 8) | *ptr++; uuid->usTimeHigh = ntohs(stmp); uuid->bClockSeqHigh = *ptr++; uuid->bClockSeqLow = *ptr++; (void) memcpy(uuid->rgbNode, ptr, 6); } static void local_uuid_copy(TSS_UUID *dst, TSS_UUID *src) { uuid_t udst, usrc; tss_uuid_convert_from(dst, udst); tss_uuid_convert_from(src, usrc); uuid_copy(udst, usrc); tss_uuid_convert_to(dst, udst); } static void local_uuid_generate(TSS_UUID *uu) { uuid_t newuuid; uuid_generate(newuuid); tss_uuid_convert_to(uu, newuuid); } static int local_copy_file(char *dst, char *src) { FILE *fdest, *fsrc; char line[BUFSIZ]; fdest = fopen(dst, "w"); if (fdest == NULL) return (-1); fsrc = fopen(src, "r"); if (fsrc == NULL) { (void) fclose(fdest); return (-1); } while (fread(line, sizeof (line), 1, fsrc)) (void) fprintf(fdest, "%s\n", line); (void) fclose(fsrc); (void) fclose(fdest); return (0); } static int remove_uuid(char *keyname) { int ret = 0; FILE *fp, *newfp; char fname[MAXPATHLEN]; char line[BUFSIZ], key[BUFSIZ], idstr[BUFSIZ]; char *tmpfname; char *p = get_tpm_keystore_path(); if (p == NULL) return (-1); (void) snprintf(fname, sizeof (fname), "%s/%s", p, TPMTOK_UUID_INDEX_FILENAME); fp = fopen(fname, "r"); if (fp == NULL) { return (-1); } tmpfname = tempnam("/tmp", "tpmtok"); newfp = fopen(tmpfname, "w+"); if (newfp == NULL) { free(tmpfname); (void) fclose(fp); return (-1); } while (!feof(fp)) { (void) fgets(line, sizeof (line), fp); if (sscanf(line, "%1024s %1024s", key, idstr) == 2) { if (strcmp(key, keyname)) (void) fprintf(newfp, "%s\n", line); } } (void) fclose(fp); (void) fclose(newfp); if (local_copy_file(fname, tmpfname) == 0) (void) unlink(tmpfname); free(tmpfname); return (ret); } static int find_uuid(char *keyname, TSS_UUID *uu) { int ret = 0, found = 0; FILE *fp = NULL; char fname[MAXPATHLEN]; char line[BUFSIZ], key[BUFSIZ], idstr[BUFSIZ]; uuid_t uuid; char *p = get_tpm_keystore_path(); if (p == NULL) return (-1); tss_uuid_convert_from(uu, uuid); (void) snprintf(fname, sizeof (fname), "%s/%s", p, TPMTOK_UUID_INDEX_FILENAME); /* Open UUID Index file */ fp = fopen(fname, "r"); if (fp == NULL) { if (errno == ENOENT) { /* initialize the file */ fp = fopen(fname, "w"); if (fp != NULL) (void) fclose(fp); } return (-1); } while (!feof(fp)) { (void) fgets(line, sizeof (line), fp); if (sscanf(line, "%1024s %1024s", key, idstr) == 2) { if (strcmp(key, keyname) == 0) { ret = uuid_parse(idstr, uuid); if (ret == 0) { found = 1; tss_uuid_convert_to(uu, uuid); } break; } } } (void) fclose(fp); if (!found) ret = -1; return (ret); } static int local_uuid_is_null(TSS_UUID *uu) { uuid_t uuid; int nulluuid; tss_uuid_convert_from(uu, uuid); nulluuid = uuid_is_null(uuid); return (nulluuid); } static int add_uuid(char *keyname, TSS_UUID *uu) { FILE *fp = NULL; char fname[MAXPATHLEN]; char idstr[BUFSIZ]; uuid_t uuid; char *p = get_tpm_keystore_path(); if (p == NULL) return (-1); tss_uuid_convert_from(uu, uuid); if (uuid_is_null(uuid)) return (-1); uuid_unparse(uuid, idstr); (void) snprintf(fname, sizeof (fname), "%s/%s", p, TPMTOK_UUID_INDEX_FILENAME); fp = fopen(fname, "a"); if (fp == NULL) return (-1); (void) fprintf(fp, "%s %s\n", keyname, idstr); (void) fclose(fp); return (0); } static UINT32 util_get_keysize_flag(CK_ULONG size) { switch (size) { case 512: return (TSS_KEY_SIZE_512); case 1024: return (TSS_KEY_SIZE_1024); case 2048: return (TSS_KEY_SIZE_2048); default: break; } return (0); } /* make sure the public exponent attribute is 65537 */ static CK_ULONG util_check_public_exponent(TEMPLATE *tmpl) { CK_BBOOL flag; CK_ATTRIBUTE *publ_exp_attr; CK_BYTE pubexp_bytes[] = { 1, 0, 1 }; CK_ULONG publ_exp, rc = 1; flag = template_attribute_find(tmpl, CKA_PUBLIC_EXPONENT, &publ_exp_attr); if (!flag) { LogError1("Couldn't find public exponent attribute"); return (CKR_TEMPLATE_INCOMPLETE); } switch (publ_exp_attr->ulValueLen) { case 3: rc = memcmp(pubexp_bytes, publ_exp_attr->pValue, 3); break; case sizeof (CK_ULONG): publ_exp = *((CK_ULONG *)publ_exp_attr->pValue); if (publ_exp == 65537) rc = 0; break; default: break; } return (rc); } TSS_RESULT set_public_modulus(TSS_HCONTEXT hContext, TSS_HKEY hKey, unsigned long size_n, unsigned char *n) { UINT64 offset; UINT32 blob_size; BYTE *blob, pub_blob[1024]; TCPA_PUBKEY pub_key; TSS_RESULT result; /* Get the TCPA_PUBKEY blob from the key object. */ result = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_KEY_BLOB, TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY, &blob_size, &blob); if (result != TSS_SUCCESS) { stlogit("Tspi_GetAttribData failed: rc=0x%0x - %s\n", result, Trspi_Error_String(result)); return (result); } offset = 0; result = Trspi_UnloadBlob_PUBKEY(&offset, blob, &pub_key); if (result != TSS_SUCCESS) { stlogit("Trspi_UnloadBlob_PUBKEY failed: rc=0x%0x - %s\n", result, Trspi_Error_String(result)); return (result); } Tspi_Context_FreeMemory(hContext, blob); /* Free the first dangling reference, putting 'n' in its place */ free(pub_key.pubKey.key); pub_key.pubKey.keyLength = size_n; pub_key.pubKey.key = n; offset = 0; Trspi_LoadBlob_PUBKEY(&offset, pub_blob, &pub_key); /* Free the second dangling reference */ free(pub_key.algorithmParms.parms); /* set the public key data in the TSS object */ result = Tspi_SetAttribData(hKey, TSS_TSPATTRIB_KEY_BLOB, TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY, (UINT32)offset, pub_blob); if (result != TSS_SUCCESS) { stlogit("Tspi_SetAttribData failed: rc=0x%0x - %s\n", result, Trspi_Error_String(result)); return (result); } return (result); } /* * Get details about the TPM to put into the token_info structure. */ CK_RV token_get_tpm_info(TSS_HCONTEXT hContext, TOKEN_DATA *td) { TSS_RESULT result; TPM_CAPABILITY_AREA capArea = TSS_TPMCAP_VERSION_VAL; UINT32 datalen; BYTE *data; TSS_HTPM hTPM; if ((result = Tspi_Context_GetTpmObject(hContext, &hTPM))) { stlogit("Tspi_Context_GetTpmObject: 0x%0x - %s", result, Trspi_Error_String(result)); return (CKR_FUNCTION_FAILED); } if ((result = Tspi_TPM_GetCapability(hTPM, capArea, 0, NULL, &datalen, &data)) != 0 || datalen == 0 || data == NULL) { stlogit("Tspi_Context_GetCapability: 0x%0x - %s", result, Trspi_Error_String(result)); return (CKR_FUNCTION_FAILED); } if (datalen > sizeof (tpmvinfo)) { Tspi_Context_FreeMemory(hContext, data); return (CKR_FUNCTION_FAILED); } (void) memcpy(&tpmvinfo, (void *)data, datalen); bzero(td->token_info.manufacturerID, sizeof (td->token_info.manufacturerID)); (void) memset(td->token_info.manufacturerID, ' ', sizeof (td->token_info.manufacturerID) - 1); (void) memcpy(td->token_info.manufacturerID, tpmvinfo.tpmVendorID, sizeof (tpmvinfo.tpmVendorID)); (void) memset(td->token_info.label, ' ', sizeof (td->token_info.label) - 1); (void) memcpy(td->token_info.label, "TPM", 3); td->token_info.hardwareVersion.major = tpmvinfo.version.major; td->token_info.hardwareVersion.minor = tpmvinfo.version.minor; td->token_info.firmwareVersion.major = tpmvinfo.version.revMajor; td->token_info.firmwareVersion.minor = tpmvinfo.version.revMinor; Tspi_Context_FreeMemory(hContext, data); return (CKR_OK); } /*ARGSUSED*/ CK_RV token_specific_session(CK_SLOT_ID slotid) { return (CKR_OK); } CK_RV token_rng(TSS_HCONTEXT hContext, CK_BYTE *output, CK_ULONG bytes) { TSS_RESULT rc; TSS_HTPM hTPM; BYTE *random_bytes = NULL; if ((rc = Tspi_Context_GetTpmObject(hContext, &hTPM))) { stlogit("Tspi_Context_GetTpmObject: 0x%0x - %s", rc, Trspi_Error_String(rc)); return (CKR_FUNCTION_FAILED); } if ((rc = Tspi_TPM_GetRandom(hTPM, bytes, &random_bytes))) { stlogit("Tspi_TPM_GetRandom: 0x%0x - %s", rc, Trspi_Error_String(rc)); return (CKR_FUNCTION_FAILED); } (void) memcpy(output, random_bytes, bytes); Tspi_Context_FreeMemory(hContext, random_bytes); return (CKR_OK); } TSS_RESULT open_tss_context(TSS_HCONTEXT *pContext) { TSS_RESULT result; if ((result = Tspi_Context_Create(pContext))) { stlogit("Tspi_Context_Create: 0x%0x - %s", result, Trspi_Error_String(result)); return (CKR_FUNCTION_FAILED); } if ((result = Tspi_Context_Connect(*pContext, NULL))) { stlogit("Tspi_Context_Connect: 0x%0x - %s", result, Trspi_Error_String(result)); Tspi_Context_Close(*pContext); *pContext = 0; return (CKR_FUNCTION_FAILED); } return (result); } /*ARGSUSED*/ static CK_RV token_specific_init(char *Correlator, CK_SLOT_ID SlotNumber, TSS_HCONTEXT *hContext) { TSS_RESULT result; result = open_tss_context(hContext); if (result) return (CKR_FUNCTION_FAILED); if ((result = Tspi_Context_GetDefaultPolicy(*hContext, &hDefaultPolicy))) { stlogit("Tspi_Context_GetDefaultPolicy: 0x%0x - %s", result, Trspi_Error_String(result)); return (CKR_FUNCTION_FAILED); } local_uuid_clear(&publicRootKeyUUID); local_uuid_clear(&privateRootKeyUUID); local_uuid_clear(&publicLeafKeyUUID); local_uuid_clear(&privateLeafKeyUUID); result = token_get_tpm_info(*hContext, nv_token_data); return (result); } /* * Given a modulus and prime from an RSA key, create a TSS_HKEY object by * wrapping the RSA key with a key from the TPM (SRK or other previously stored * key). */ static CK_RV token_wrap_sw_key( TSS_HCONTEXT hContext, int size_n, unsigned char *n, int size_p, unsigned char *p, TSS_HKEY hParentKey, TSS_FLAG initFlags, TSS_HKEY *phKey) { TSS_RESULT result; UINT32 key_size; key_size = util_get_keysize_flag(size_n * 8); if (initFlags == 0) { return (CKR_FUNCTION_FAILED); } /* create the TSS key object */ result = Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_RSAKEY, TSS_KEY_MIGRATABLE | initFlags | key_size, phKey); if (result != TSS_SUCCESS) { stlogit("Tspi_Context_CreateObject: 0x%0x - %s", result, Trspi_Error_String(result)); return (CKR_FUNCTION_FAILED); } result = set_public_modulus(hContext, *phKey, size_n, n); if (result != TSS_SUCCESS) { Tspi_Context_CloseObject(hContext, *phKey); *phKey = NULL_HKEY; return (CKR_FUNCTION_FAILED); } /* set the private key data in the TSS object */ result = Tspi_SetAttribData(*phKey, TSS_TSPATTRIB_KEY_BLOB, TSS_TSPATTRIB_KEYBLOB_PRIVATE_KEY, size_p, p); if (result != TSS_SUCCESS) { stlogit("Tspi_SetAttribData: 0x%x - %s", result, Trspi_Error_String(result)); Tspi_Context_CloseObject(hContext, *phKey); *phKey = NULL_HKEY; return (CKR_FUNCTION_FAILED); } result = tss_assign_secret_key_policy(hContext, TSS_POLICY_MIGRATION, *phKey, NULL); if (TPMTOK_TSS_KEY_TYPE(initFlags) == TSS_KEY_TYPE_LEGACY) { if ((result = Tspi_SetAttribUint32(*phKey, TSS_TSPATTRIB_KEY_INFO, TSS_TSPATTRIB_KEYINFO_ENCSCHEME, TSS_ES_RSAESPKCSV15))) { stlogit("Tspi_SetAttribUint32: 0x%0x - %s\n", result, Trspi_Error_String(result)); Tspi_Context_CloseObject(hContext, *phKey); return (CKR_FUNCTION_FAILED); } if ((result = Tspi_SetAttribUint32(*phKey, TSS_TSPATTRIB_KEY_INFO, TSS_TSPATTRIB_KEYINFO_SIGSCHEME, TSS_SS_RSASSAPKCS1V15_DER))) { stlogit("Tspi_SetAttribUint32: 0x%0x - %s\n", result, Trspi_Error_String(result)); Tspi_Context_CloseObject(hContext, *phKey); return (CKR_FUNCTION_FAILED); } } result = Tspi_Key_WrapKey(*phKey, hParentKey, NULL_HPCRS); if (result != TSS_SUCCESS) { stlogit("Tspi_Key_WrapKey: 0x%0x - %s", result, Trspi_Error_String(result)); Tspi_Context_CloseObject(hContext, *phKey); *phKey = NULL_HKEY; return (CKR_FUNCTION_FAILED); } return (CKR_OK); } /* * Create a TPM key blob for an imported key. This function is only called when * a key is in active use, so any failure should trickle through. */ static CK_RV token_wrap_key_object(TSS_HCONTEXT hContext, CK_OBJECT_HANDLE ckObject, TSS_HKEY hParentKey, TSS_HKEY *phKey) { CK_RV rc = CKR_OK; CK_ATTRIBUTE *attr = NULL, *new_attr, *prime_attr; CK_ULONG class, key_type; OBJECT *obj; TSS_RESULT result; TSS_FLAG initFlags = 0; BYTE *rgbBlob; UINT32 ulBlobLen; if ((rc = object_mgr_find_in_map1(hContext, ckObject, &obj))) { return (rc); } /* if the object isn't a key, fail */ if (template_attribute_find(obj->template, CKA_KEY_TYPE, &attr) == FALSE) { return (CKR_TEMPLATE_INCOMPLETE); } key_type = *((CK_ULONG *)attr->pValue); if (key_type != CKK_RSA) { return (CKR_TEMPLATE_INCONSISTENT); } if (template_attribute_find(obj->template, CKA_CLASS, &attr) == FALSE) { return (CKR_TEMPLATE_INCOMPLETE); } class = *((CK_ULONG *)attr->pValue); if (class == CKO_PRIVATE_KEY) { /* * In order to create a full TSS key blob using a PKCS#11 * private key object, we need one of the two primes, the * modulus and the private exponent and we need the public * exponent to be correct. */ /* * Check the least likely attribute to exist first, the * primes. */ if (template_attribute_find(obj->template, CKA_PRIME_1, &prime_attr) == FALSE) { if (template_attribute_find(obj->template, CKA_PRIME_2, &prime_attr) == FALSE) { return (CKR_TEMPLATE_INCOMPLETE); } } /* Make sure the public exponent is usable */ if ((rc = util_check_public_exponent(obj->template))) { return (CKR_TEMPLATE_INCONSISTENT); } /* get the modulus */ if (template_attribute_find(obj->template, CKA_MODULUS, &attr) == FALSE) { return (CKR_TEMPLATE_INCOMPLETE); } /* make sure the key size is usable */ initFlags = util_get_keysize_flag(attr->ulValueLen * 8); if (initFlags == 0) { return (CKR_TEMPLATE_INCONSISTENT); } /* generate the software based key */ if ((rc = token_wrap_sw_key(hContext, (int)attr->ulValueLen, attr->pValue, (int)prime_attr->ulValueLen, prime_attr->pValue, hParentKey, TSS_KEY_TYPE_LEGACY | TSS_KEY_NO_AUTHORIZATION, phKey))) { return (rc); } } else if (class == CKO_PUBLIC_KEY) { /* Make sure the public exponent is usable */ if ((util_check_public_exponent(obj->template))) { return (CKR_TEMPLATE_INCONSISTENT); } /* grab the modulus to put into the TSS key object */ if (template_attribute_find(obj->template, CKA_MODULUS, &attr) == FALSE) { return (CKR_TEMPLATE_INCONSISTENT); } /* make sure the key size is usable */ initFlags = util_get_keysize_flag(attr->ulValueLen * 8); if (initFlags == 0) { return (CKR_TEMPLATE_INCONSISTENT); } initFlags |= TSS_KEY_MIGRATABLE | TSS_KEY_NO_AUTHORIZATION | TSS_KEY_TYPE_LEGACY; if ((result = Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_RSAKEY, initFlags, phKey))) { stlogit("Tspi_Context_CreateObject: 0x%0x - %s", result, Trspi_Error_String(result)); return (result); } if ((result = set_public_modulus(hContext, *phKey, attr->ulValueLen, attr->pValue))) { Tspi_Context_CloseObject(hContext, *phKey); *phKey = NULL_HKEY; return (CKR_FUNCTION_FAILED); } result = tss_assign_secret_key_policy(hContext, TSS_POLICY_MIGRATION, *phKey, NULL); if (result) { Tspi_Context_CloseObject(hContext, *phKey); *phKey = NULL_HKEY; return (CKR_FUNCTION_FAILED); } result = set_legacy_key_params(*phKey); if (result) { Tspi_Context_CloseObject(hContext, *phKey); *phKey = NULL_HKEY; return (CKR_FUNCTION_FAILED); } } else { return (CKR_FUNCTION_FAILED); } /* grab the entire key blob to put into the PKCS#11 object */ if ((result = Tspi_GetAttribData(*phKey, TSS_TSPATTRIB_KEY_BLOB, TSS_TSPATTRIB_KEYBLOB_BLOB, &ulBlobLen, &rgbBlob))) { stlogit("Tspi_GetAttribData: 0x%0x - %s", result, Trspi_Error_String(result)); return (CKR_FUNCTION_FAILED); } /* insert the key blob into the object */ if ((rc = build_attribute(CKA_IBM_OPAQUE, rgbBlob, ulBlobLen, &new_attr))) { Tspi_Context_FreeMemory(hContext, rgbBlob); return (rc); } (void) template_update_attribute(obj->template, new_attr); Tspi_Context_FreeMemory(hContext, rgbBlob); /* * If this is a token object, save it with the new attribute * so that we don't have to go down this path again. */ if (!object_is_session_object(obj)) { rc = save_token_object(hContext, obj); } return (rc); } static TSS_RESULT tss_assign_secret_key_policy(TSS_HCONTEXT hContext, TSS_FLAG policyType, TSS_HKEY hKey, CK_CHAR *passHash) { TSS_RESULT result; TSS_HPOLICY hPolicy; if ((result = Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_POLICY, policyType, &hPolicy))) { stlogit("Tspi_Context_CreateObject: 0x%0x - %s", result, Trspi_Error_String(result)); return (result); } if ((result = Tspi_Policy_AssignToObject(hPolicy, hKey))) { stlogit("Tspi_Policy_AssignToObject: 0x%0x - %s", result, Trspi_Error_String(result)); goto done; } if (passHash == NULL) { result = Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_NONE, 0, NULL); } else { result = Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_SHA1, SHA1_DIGEST_LENGTH, passHash); } if (result != TSS_SUCCESS) { stlogit("Tspi_Policy_SetSecret: 0x%0x - %s", result, Trspi_Error_String(result)); goto done; } done: if (result != TSS_SUCCESS) Tspi_Context_CloseObject(hContext, hPolicy); return (result); } /* * Take a key from the TSS store (on-disk) and load it into the TPM, wrapped * by an already TPM-resident key and protected with a PIN (optional). */ static CK_RV token_load_key( TSS_HCONTEXT hContext, CK_OBJECT_HANDLE ckKey, TSS_HKEY hParentKey, CK_CHAR_PTR passHash, TSS_HKEY *phKey) { TSS_RESULT result; CK_RV rc; /* * The key blob wasn't found, load the parts of the key * from the object DB and create a new key object that * gets loaded into the TPM, wrapped with the parent key. */ if ((rc = token_wrap_key_object(hContext, ckKey, hParentKey, phKey))) { return (rc); } /* * Assign the PIN hash (optional) to the newly loaded key object, * if this PIN is incorrect, the TPM will not be able to decrypt * the private key and use it. */ result = tss_assign_secret_key_policy(hContext, TSS_POLICY_USAGE, *phKey, passHash); return (result); } /* * Load the SRK into the TPM by referencing its well-known UUID and using the * default SRK PIN (20 bytes of 0x00). * * NOTE - if the SRK PIN is changed by an administrative tool, this code will * fail because it assumes that the well-known PIN is still being used. */ static TSS_RESULT token_load_srk(TSS_HCONTEXT hContext, TSS_HKEY *hSRK) { TSS_HPOLICY hPolicy; TSS_RESULT result; TSS_UUID SRK_UUID = TSS_UUID_SRK; BYTE wellKnown[] = TSS_WELL_KNOWN_SECRET; TSS_HTPM hTPM; if ((result = Tspi_Context_GetTpmObject(hContext, &hTPM))) { stlogit("Tspi_Context_GetTpmObject: 0x%0x - %s", result, Trspi_Error_String(result)); return (CKR_FUNCTION_FAILED); } /* load the SRK */ if ((result = Tspi_Context_LoadKeyByUUID(hContext, TSS_PS_TYPE_SYSTEM, SRK_UUID, hSRK))) { stlogit("Tspi_Context_LoadKeyByUUID: 0x%0x - %s", result, Trspi_Error_String(result)); goto done; } if ((result = Tspi_GetPolicyObject(*hSRK, TSS_POLICY_USAGE, &hPolicy))) { stlogit("Tspi_GetPolicyObject: 0x%0x - %s", result, Trspi_Error_String(result)); goto done; } if ((result = Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_SHA1, sizeof (wellKnown), wellKnown))) { stlogit("Tspi_Policy_SetSecret: 0x%0x - %s", result, Trspi_Error_String(result)); goto done; } done: return (result); } static TSS_RESULT tss_find_and_load_key(TSS_HCONTEXT hContext, char *keyid, TSS_UUID *uuid, TSS_HKEY hParent, BYTE *hash, TSS_HKEY *hKey) { TSS_RESULT result; if (local_uuid_is_null(uuid) && find_uuid(keyid, uuid)) { /* The UUID was not created or saved yet */ return (1); } result = Tspi_Context_GetKeyByUUID(hContext, TSS_PS_TYPE_USER, *uuid, hKey); if (result) { stlogit("Tspi_Context_GetKeyByUUID: 0x%0x - %s", result, Trspi_Error_String(result)); return (result); } if (hash != NULL) { result = tss_assign_secret_key_policy(hContext, TSS_POLICY_USAGE, *hKey, (CK_BYTE *)hash); if (result) return (result); } result = Tspi_Key_LoadKey(*hKey, hParent); if (result) stlogit("Tspi_Key_LoadKey: 0x%0x - %s", result, Trspi_Error_String(result)); return (result); } static TSS_RESULT token_load_public_root_key(TSS_HCONTEXT hContext) { TSS_RESULT result; TSS_HKEY hSRK; if (hPublicRootKey != NULL_HKEY) return (TSS_SUCCESS); if ((result = token_load_srk(hContext, &hSRK))) { return (result); } result = tss_find_and_load_key(hContext, TPMTOK_PUBLIC_ROOT_KEY_ID, &publicRootKeyUUID, hSRK, NULL, &hPublicRootKey); if (result) return (result); return (result); } static TSS_RESULT set_legacy_key_params(TSS_HKEY hKey) { TSS_RESULT result; if ((result = Tspi_SetAttribUint32(hKey, TSS_TSPATTRIB_KEY_INFO, TSS_TSPATTRIB_KEYINFO_ENCSCHEME, TSS_ES_RSAESPKCSV15))) { stlogit("Tspi_SetAttribUint32: 0x%0x - %s", result, Trspi_Error_String(result)); return (result); } if ((result = Tspi_SetAttribUint32(hKey, TSS_TSPATTRIB_KEY_INFO, TSS_TSPATTRIB_KEYINFO_SIGSCHEME, TSS_SS_RSASSAPKCS1V15_DER))) { stlogit("Tspi_SetAttribUint32: 0x%0x - %s", result, Trspi_Error_String(result)); return (result); } return (result); } static TSS_RESULT tss_generate_key(TSS_HCONTEXT hContext, TSS_FLAG initFlags, BYTE *passHash, TSS_HKEY hParentKey, TSS_HKEY *phKey) { TSS_RESULT result; TSS_HPOLICY hMigPolicy; if ((result = Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_RSAKEY, initFlags, phKey))) { stlogit("Tspi_Context_CreateObject: 0x%0x - %s", result, Trspi_Error_String(result)); return (result); } result = tss_assign_secret_key_policy(hContext, TSS_POLICY_USAGE, *phKey, passHash); if (result) { Tspi_Context_CloseObject(hContext, *phKey); return (result); } if (TPMTOK_TSS_KEY_MIG_TYPE(initFlags) == TSS_KEY_MIGRATABLE) { if ((result = Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_POLICY, TSS_POLICY_MIGRATION, &hMigPolicy))) { stlogit("Tspi_Context_CreateObject: 0x%0x - %s", result, Trspi_Error_String(result)); Tspi_Context_CloseObject(hContext, *phKey); return (result); } if (passHash == NULL) { result = Tspi_Policy_SetSecret(hMigPolicy, TSS_SECRET_MODE_NONE, 0, NULL); } else { result = Tspi_Policy_SetSecret(hMigPolicy, TSS_SECRET_MODE_SHA1, 20, passHash); } if (result != TSS_SUCCESS) { stlogit("Tspi_Policy_SetSecret: 0x%0x - %s", result, Trspi_Error_String(result)); Tspi_Context_CloseObject(hContext, *phKey); Tspi_Context_CloseObject(hContext, hMigPolicy); return (result); } if ((result = Tspi_Policy_AssignToObject(hMigPolicy, *phKey))) { stlogit("Tspi_Policy_AssignToObject: 0x%0x - %s", result, Trspi_Error_String(result)); Tspi_Context_CloseObject(hContext, *phKey); Tspi_Context_CloseObject(hContext, hMigPolicy); return (result); } } if (TPMTOK_TSS_KEY_TYPE(initFlags) == TSS_KEY_TYPE_LEGACY) { result = set_legacy_key_params(*phKey); if (result) { Tspi_Context_CloseObject(hContext, *phKey); Tspi_Context_CloseObject(hContext, hMigPolicy); return (result); } } if ((result = Tspi_Key_CreateKey(*phKey, hParentKey, 0))) { stlogit("Tspi_Key_CreateKey: 0x%0x - %s", result, Trspi_Error_String(result)); Tspi_Context_CloseObject(hContext, *phKey); Tspi_Context_CloseObject(hContext, hMigPolicy); } return (result); } static TSS_RESULT tss_change_auth( TSS_HCONTEXT hContext, TSS_HKEY hObjectToChange, TSS_HKEY hParentObject, TSS_UUID objUUID, TSS_UUID parentUUID, CK_CHAR *passHash) { TSS_RESULT result; TSS_HPOLICY hPolicy; TSS_HKEY oldkey; if ((result = Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_POLICY, TSS_POLICY_USAGE, &hPolicy))) { stlogit("Tspi_Context_CreateObject: 0x%0x - %s", result, Trspi_Error_String(result)); return (result); } if ((result = Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_SHA1, SHA1_DIGEST_LENGTH, passHash))) { stlogit("Tspi_Policy_SetSecret: 0x%0x - %s", result, Trspi_Error_String(result)); return (result); } if ((result = Tspi_ChangeAuth(hObjectToChange, hParentObject, hPolicy))) { stlogit("Tspi_ChangeAuth: 0x%0x - %s", result, Trspi_Error_String(result)); } /* * Update the PS key by unregistering the key UUID and then * re-registering with the same UUID. This forces the updated * auth data associated with the key to be stored in PS so * the new PIN can be used next time. */ if ((result = Tspi_Context_UnregisterKey(hContext, TSS_PS_TYPE_USER, objUUID, &oldkey))) stlogit("Tspi_Context_UnregisterKey: 0x%0x - %s", result, Trspi_Error_String(result)); if ((result = Tspi_Context_RegisterKey(hContext, hObjectToChange, TSS_PS_TYPE_USER, objUUID, TSS_PS_TYPE_USER, parentUUID))) stlogit("Tspi_Context_RegisterKey: 0x%0x - %s", result, Trspi_Error_String(result)); return (result); } static CK_RV token_generate_leaf_key(TSS_HCONTEXT hContext, int key_type, CK_CHAR_PTR passHash, TSS_HKEY *phKey) { CK_RV rc = CKR_FUNCTION_FAILED; TSS_RESULT result; TSS_HKEY hParentKey; TSS_UUID newuuid, parentUUID; char *keyid; TSS_FLAG initFlags = TSS_KEY_MIGRATABLE | TSS_KEY_TYPE_BIND | TSS_KEY_SIZE_2048 | TSS_KEY_AUTHORIZATION; switch (key_type) { case TPMTOK_PUBLIC_LEAF_KEY: hParentKey = hPublicRootKey; keyid = TPMTOK_PUBLIC_LEAF_KEY_ID; local_uuid_copy(&parentUUID, &publicRootKeyUUID); break; case TPMTOK_PRIVATE_LEAF_KEY: hParentKey = hPrivateRootKey; keyid = TPMTOK_PRIVATE_LEAF_KEY_ID; local_uuid_copy(&parentUUID, &privateRootKeyUUID); break; default: stlogit("Unknown key type 0x%0x", key_type); goto done; } if (result = tss_generate_key(hContext, initFlags, passHash, hParentKey, phKey)) { return (rc); } /* * - generate newUUID * - Tspi_Context_RegisterKey(hContext, hPrivateRootKey, * USER, newUUID, USER, parentUUID); * - store newUUID */ (void) local_uuid_generate(&newuuid); result = Tspi_Context_RegisterKey(hContext, *phKey, TSS_PS_TYPE_USER, newuuid, TSS_PS_TYPE_USER, parentUUID); if (result == TSS_SUCCESS) { int ret; /* * Add the UUID to the token UUID index. */ ret = add_uuid(keyid, &newuuid); if (ret) result = Tspi_Context_UnregisterKey(hContext, TSS_PS_TYPE_USER, newuuid, phKey); else rc = CKR_OK; } done: return (rc); } /* * PINs are verified by attempting to bind/unbind random data using a * TPM resident key that has the PIN being tested assigned as its "secret". * If the PIN is incorrect, the unbind operation will fail. */ static CK_RV token_verify_pin(TSS_HCONTEXT hContext, TSS_HKEY hKey) { TSS_HENCDATA hEncData; UINT32 ulUnboundDataLen; BYTE *rgbUnboundData = NULL; BYTE rgbData[16]; TSS_RESULT result; CK_RV rc = CKR_FUNCTION_FAILED; if ((result = Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, &hEncData))) { stlogit("Tspi_Context_CreateObject: 0x%0x - %s", result, Trspi_Error_String(result)); goto done; } /* Use some random data */ rc = token_rng(hContext, rgbData, sizeof (rgbData)); if (rc) goto done; if ((result = Tspi_Data_Bind(hEncData, hKey, sizeof (rgbData), rgbData))) { stlogit("Tspi_Data_Bind: 0x%0x - %s", result, Trspi_Error_String(result)); goto done; } /* unbind the junk data to test the key's auth data */ result = Tspi_Data_Unbind(hEncData, hKey, &ulUnboundDataLen, &rgbUnboundData); if (result == TPM_E_AUTHFAIL) { rc = CKR_PIN_INCORRECT; stlogit("Tspi_Data_Unbind: 0x%0x - %s", result, Trspi_Error_String(result)); goto done; } else if (result != TSS_SUCCESS) { stlogit("Tspi_Data_Unbind: 0x%0x - %s", result, Trspi_Error_String(result)); rc = CKR_FUNCTION_FAILED; goto done; } if (memcmp(rgbUnboundData, rgbData, ulUnboundDataLen)) rc = CKR_PIN_INCORRECT; else rc = CKR_OK; done: if (rgbUnboundData != NULL) Tspi_Context_FreeMemory(hContext, rgbUnboundData); Tspi_Context_CloseObject(hContext, hEncData); return (rc); } static CK_RV token_create_private_tree(TSS_HCONTEXT hContext, CK_BYTE *pinHash) { CK_RV rc; TSS_RESULT result; int ret; TSS_FLAG initFlags = TSS_KEY_SIZE_2048 | TSS_KEY_NO_AUTHORIZATION | TSS_KEY_TYPE_STORAGE; TSS_UUID SRK_UUID = TSS_UUID_SRK; TSS_HKEY hSRK; if (token_load_srk(hContext, &hSRK)) return (CKR_FUNCTION_FAILED); /* * - create UUID privateRootKeyUUID * - Tspi_Context_RegisterKey(hContext, hPrivateRootKey, * USER, privateRootKeyUUID, system, UUID_SRK); * - store privateRootKeyUUID in users private token space. */ if ((result = tss_generate_key(hContext, initFlags, NULL, hSRK, &hPrivateRootKey))) { return (result); } if (local_uuid_is_null(&privateRootKeyUUID)) local_uuid_generate(&privateRootKeyUUID); result = Tspi_Context_RegisterKey(hContext, hPrivateRootKey, TSS_PS_TYPE_USER, privateRootKeyUUID, TSS_PS_TYPE_SYSTEM, SRK_UUID); if (result) { local_uuid_clear(&privateRootKeyUUID); return (result); } ret = add_uuid(TPMTOK_PRIVATE_ROOT_KEY_ID, &privateRootKeyUUID); if (ret) { result = Tspi_Context_UnregisterKey(hContext, TSS_PS_TYPE_USER, privateRootKeyUUID, &hPrivateRootKey); return (CKR_FUNCTION_FAILED); } if ((result = Tspi_Key_LoadKey(hPrivateRootKey, hSRK))) { stlogit("Tspi_Key_LoadKey: 0x%0x - %s", result, Trspi_Error_String(result)); Tspi_Context_CloseObject(hContext, hPrivateRootKey); (void) remove_uuid(TPMTOK_PRIVATE_ROOT_KEY_ID); local_uuid_clear(&privateRootKeyUUID); hPrivateRootKey = NULL_HKEY; return (CKR_FUNCTION_FAILED); } /* generate the private leaf key */ if ((rc = token_generate_leaf_key(hContext, TPMTOK_PRIVATE_LEAF_KEY, pinHash, &hPrivateLeafKey))) { return (rc); } if ((result = Tspi_Key_LoadKey(hPrivateLeafKey, hPrivateRootKey))) { stlogit("Tspi_Key_LoadKey: 0x%0x - %s", result, Trspi_Error_String(result)); (void) Tspi_Context_UnregisterKey(hContext, TSS_PS_TYPE_USER, privateLeafKeyUUID, &hPrivateLeafKey); (void) remove_uuid(TPMTOK_PRIVATE_LEAF_KEY_ID); local_uuid_clear(&privateLeafKeyUUID); (void) Tspi_Context_UnregisterKey(hContext, TSS_PS_TYPE_USER, privateRootKeyUUID, &hPrivateRootKey); (void) remove_uuid(TPMTOK_PRIVATE_ROOT_KEY_ID); local_uuid_clear(&privateRootKeyUUID); Tspi_Context_CloseObject(hContext, hPrivateRootKey); hPrivateRootKey = NULL_HKEY; Tspi_Context_CloseObject(hContext, hPrivateLeafKey); hPrivateRootKey = NULL_HKEY; return (CKR_FUNCTION_FAILED); } return (rc); } static CK_RV token_create_public_tree(TSS_HCONTEXT hContext, CK_BYTE *pinHash) { CK_RV rc; TSS_RESULT result; int ret; TSS_FLAG initFlags = TSS_KEY_SIZE_2048 | TSS_KEY_NO_AUTHORIZATION | TSS_KEY_TYPE_STORAGE; TSS_UUID srk_uuid = TSS_UUID_SRK; TSS_HKEY hSRK; if (token_load_srk(hContext, &hSRK)) return (CKR_FUNCTION_FAILED); /* * - create publicRootKeyUUID * - Tspi_Context_RegisterKey(hContext, hPublicRootKey, * USER, publicRootKeyUUID, system, UUID_SRK); * - store publicRootKeyUUID in users private token space. */ if ((result = tss_generate_key(hContext, initFlags, NULL, hSRK, &hPublicRootKey))) { return (CKR_FUNCTION_FAILED); } if (local_uuid_is_null(&publicRootKeyUUID)) local_uuid_generate(&publicRootKeyUUID); result = Tspi_Context_RegisterKey(hContext, hPublicRootKey, TSS_PS_TYPE_USER, publicRootKeyUUID, TSS_PS_TYPE_SYSTEM, srk_uuid); if (result) { local_uuid_clear(&publicRootKeyUUID); return (CKR_FUNCTION_FAILED); } ret = add_uuid(TPMTOK_PUBLIC_ROOT_KEY_ID, &publicRootKeyUUID); if (ret) { result = Tspi_Context_UnregisterKey(hContext, TSS_PS_TYPE_USER, publicRootKeyUUID, &hPublicRootKey); /* does result matter here? */ return (CKR_FUNCTION_FAILED); } /* Load the newly created publicRootKey into the TPM using the SRK */ if ((result = Tspi_Key_LoadKey(hPublicRootKey, hSRK))) { stlogit("Tspi_Key_LoadKey: 0x%x - %s", result, Trspi_Error_String(result)); Tspi_Context_CloseObject(hContext, hPublicRootKey); hPublicRootKey = NULL_HKEY; return (CKR_FUNCTION_FAILED); } /* create the SO's leaf key */ if ((rc = token_generate_leaf_key(hContext, TPMTOK_PUBLIC_LEAF_KEY, pinHash, &hPublicLeafKey))) { return (rc); } if ((result = Tspi_Key_LoadKey(hPublicLeafKey, hPublicRootKey))) { stlogit("Tspi_Key_LoadKey: 0x%0x - %s", result, Trspi_Error_String(result)); /* Unregister keys and clear UUIDs */ (void) Tspi_Context_UnregisterKey(hContext, TSS_PS_TYPE_USER, publicLeafKeyUUID, &hPublicLeafKey); (void) remove_uuid(TPMTOK_PUBLIC_LEAF_KEY_ID); (void) Tspi_Context_UnregisterKey(hContext, TSS_PS_TYPE_USER, publicRootKeyUUID, &hPublicRootKey); (void) remove_uuid(TPMTOK_PUBLIC_ROOT_KEY_ID); Tspi_Context_CloseObject(hContext, hPublicRootKey); hPublicRootKey = NULL_HKEY; Tspi_Context_CloseObject(hContext, hPublicLeafKey); hPublicLeafKey = NULL_HKEY; return (CKR_FUNCTION_FAILED); } return (rc); } CK_RV token_specific_login( TSS_HCONTEXT hContext, CK_USER_TYPE userType, CK_CHAR_PTR pPin, CK_ULONG ulPinLen) { CK_RV rc; CK_BYTE hash_sha[SHA1_DIGEST_LENGTH]; TSS_RESULT result; TSS_HKEY hSRK; /* Make sure the SRK is loaded into the TPM */ if ((result = token_load_srk(hContext, &hSRK))) { return (CKR_FUNCTION_FAILED); } if ((rc = compute_sha(pPin, ulPinLen, hash_sha))) { return (CKR_FUNCTION_FAILED); } if (userType == CKU_USER) { /* * If the public root key doesn't exist yet, * the SO hasn't init'd the token. */ if ((result = token_load_public_root_key(hContext))) { if (result == TPM_E_DECRYPT_ERROR) { return (CKR_USER_PIN_NOT_INITIALIZED); } } /* * - find privateRootKeyUUID * - load by UUID (SRK parent) */ if (local_uuid_is_null(&privateRootKeyUUID) && find_uuid(TPMTOK_PRIVATE_ROOT_KEY_ID, &privateRootKeyUUID)) { if (memcmp(hash_sha, default_user_pin_sha, SHA1_DIGEST_LENGTH)) return (CKR_PIN_INCORRECT); not_initialized = 1; return (CKR_OK); } if ((rc = verify_user_pin(hContext, hash_sha))) { return (rc); } (void) memcpy(current_user_pin_sha, hash_sha, SHA1_DIGEST_LENGTH); rc = load_private_token_objects(hContext); if (rc == CKR_OK) { (void) XProcLock(xproclock); global_shm->priv_loaded = TRUE; (void) XProcUnLock(xproclock); } } else { /* * SO login logic: * * - find publicRootKey UUID * - load by UUID wrap with hSRK from above */ if (local_uuid_is_null(&publicRootKeyUUID) && find_uuid(TPMTOK_PUBLIC_ROOT_KEY_ID, &publicRootKeyUUID)) { if (memcmp(hash_sha, default_so_pin_sha, SHA1_DIGEST_LENGTH)) return (CKR_PIN_INCORRECT); not_initialized = 1; return (CKR_OK); } if (hPublicRootKey == NULL_HKEY) { result = tss_find_and_load_key( hContext, TPMTOK_PUBLIC_ROOT_KEY_ID, &publicRootKeyUUID, hSRK, NULL, &hPublicRootKey); if (result) return (CKR_FUNCTION_FAILED); } /* find, load the public leaf key */ if (hPublicLeafKey == NULL_HKEY) { result = tss_find_and_load_key( hContext, TPMTOK_PUBLIC_LEAF_KEY_ID, &publicLeafKeyUUID, hPublicRootKey, hash_sha, &hPublicLeafKey); if (result) return (CKR_FUNCTION_FAILED); } if ((rc = token_verify_pin(hContext, hPublicLeafKey))) { return (rc); } (void) memcpy(current_so_pin_sha, hash_sha, SHA1_DIGEST_LENGTH); } return (rc); } CK_RV token_specific_logout(TSS_HCONTEXT hContext) { if (hPrivateLeafKey != NULL_HKEY) { Tspi_Key_UnloadKey(hPrivateLeafKey); hPrivateLeafKey = NULL_HKEY; } else if (hPublicLeafKey != NULL_HKEY) { Tspi_Key_UnloadKey(hPublicLeafKey); hPublicLeafKey = NULL_HKEY; } local_uuid_clear(&publicRootKeyUUID); local_uuid_clear(&publicLeafKeyUUID); local_uuid_clear(&privateRootKeyUUID); local_uuid_clear(&privateLeafKeyUUID); (void) memset(current_so_pin_sha, 0, SHA1_DIGEST_LENGTH); (void) memset(current_user_pin_sha, 0, SHA1_DIGEST_LENGTH); (void) object_mgr_purge_private_token_objects(hContext); return (CKR_OK); } /*ARGSUSED*/ CK_RV token_specific_init_pin(TSS_HCONTEXT hContext, CK_CHAR_PTR pPin, CK_ULONG ulPinLen) { /* * Since the SO must log in before calling C_InitPIN, we will * be able to return (CKR_OK) automatically here. * This is because the USER key structure is created at the * time of their first login, not at C_InitPIN time. */ return (CKR_OK); } static CK_RV check_pin_properties(CK_USER_TYPE userType, CK_BYTE *pinHash, CK_ULONG ulPinLen) { /* make sure the new PIN is different */ if (userType == CKU_USER) { if (!memcmp(pinHash, default_user_pin_sha, SHA1_DIGEST_LENGTH)) { LogError1("new PIN must not be the default"); return (CKR_PIN_INVALID); } } else { if (!memcmp(pinHash, default_so_pin_sha, SHA1_DIGEST_LENGTH)) { LogError1("new PIN must not be the default"); return (CKR_PIN_INVALID); } } if (ulPinLen > MAX_PIN_LEN || ulPinLen < MIN_PIN_LEN) { LogError1("New PIN is out of size range"); return (CKR_PIN_LEN_RANGE); } return (CKR_OK); } /* * This function is called from set_pin only, where a non-logged-in public * session can provide the user pin which must be verified. This function * assumes that the pin has already been set once, so there's no migration * path option or checking of the default user pin. */ static CK_RV verify_user_pin(TSS_HCONTEXT hContext, CK_BYTE *hash_sha) { CK_RV rc; TSS_RESULT result; TSS_HKEY hSRK; if (token_load_srk(hContext, &hSRK)) return (CKR_FUNCTION_FAILED); /* * Verify the user by loading the privateLeafKey * into the TPM (if it's not already) and then * call the verify_pin operation. * * The hashed PIN is assigned to the private leaf key. * If it is incorrect (not the same as the one originally * used when the key was created), the verify operation * will fail. */ if (hPrivateRootKey == NULL_HKEY) { result = tss_find_and_load_key( hContext, TPMTOK_PRIVATE_ROOT_KEY_ID, &privateRootKeyUUID, hSRK, NULL, &hPrivateRootKey); if (result) return (CKR_FUNCTION_FAILED); } if (hPrivateLeafKey == NULL_HKEY) { result = tss_find_and_load_key( hContext, TPMTOK_PRIVATE_LEAF_KEY_ID, &privateLeafKeyUUID, hPrivateRootKey, hash_sha, &hPrivateLeafKey); if (result) return (CKR_FUNCTION_FAILED); } /* * Verify that the PIN is correct by attempting to wrap/unwrap some * random data. */ if ((rc = token_verify_pin(hContext, hPrivateLeafKey))) { return (rc); } return (CKR_OK); } CK_RV token_specific_set_pin(ST_SESSION_HANDLE session, CK_CHAR_PTR pOldPin, CK_ULONG ulOldPinLen, CK_CHAR_PTR pNewPin, CK_ULONG ulNewPinLen) { SESSION *sess = session_mgr_find(session.sessionh); CK_BYTE oldpin_hash[SHA1_DIGEST_LENGTH]; CK_BYTE newpin_hash[SHA1_DIGEST_LENGTH]; CK_RV rc; TSS_HKEY hSRK; if (!sess) { return (CKR_SESSION_HANDLE_INVALID); } if ((rc = compute_sha(pOldPin, ulOldPinLen, oldpin_hash))) { return (CKR_FUNCTION_FAILED); } if ((rc = compute_sha(pNewPin, ulNewPinLen, newpin_hash))) { return (CKR_FUNCTION_FAILED); } if (token_load_srk(sess->hContext, &hSRK)) { return (CKR_FUNCTION_FAILED); } /* * From the PKCS#11 2.20 spec: "C_SetPIN modifies the PIN of * the user that is currently logged in, or the CKU_USER PIN * if the session is not logged in." * A non R/W session fails with CKR_SESSION_READ_ONLY. */ if (sess->session_info.state == CKS_RW_USER_FUNCTIONS || sess->session_info.state == CKS_RW_PUBLIC_SESSION) { if (not_initialized) { if (memcmp(oldpin_hash, default_user_pin_sha, SHA1_DIGEST_LENGTH)) { return (CKR_PIN_INCORRECT); } if ((rc = check_pin_properties(CKU_USER, newpin_hash, ulNewPinLen))) { return (rc); } if ((rc = token_create_private_tree(sess->hContext, newpin_hash))) { return (CKR_FUNCTION_FAILED); } nv_token_data->token_info.flags &= ~(CKF_USER_PIN_TO_BE_CHANGED); nv_token_data->token_info.flags |= CKF_USER_PIN_INITIALIZED; nv_token_data->token_info.flags &= ~(CKF_USER_PIN_TO_BE_CHANGED); nv_token_data->token_info.flags |= CKF_USER_PIN_INITIALIZED; return (save_token_data(nv_token_data)); } if (sess->session_info.state == CKS_RW_USER_FUNCTIONS) { /* if we're already logged in, just verify the hash */ if (memcmp(current_user_pin_sha, oldpin_hash, SHA1_DIGEST_LENGTH)) { return (CKR_PIN_INCORRECT); } } else { if ((rc = verify_user_pin(sess->hContext, oldpin_hash))) { return (rc); } } if ((rc = check_pin_properties(CKU_USER, newpin_hash, ulNewPinLen))) return (rc); /* change the auth on the TSS object */ if (tss_change_auth(sess->hContext, hPrivateLeafKey, hPrivateRootKey, privateLeafKeyUUID, privateRootKeyUUID, newpin_hash)) return (CKR_FUNCTION_FAILED); } else if (sess->session_info.state == CKS_RW_SO_FUNCTIONS) { if (not_initialized) { if (memcmp(default_so_pin_sha, oldpin_hash, SHA1_DIGEST_LENGTH)) return (CKR_PIN_INCORRECT); if ((rc = check_pin_properties(CKU_SO, newpin_hash, ulNewPinLen))) return (rc); if ((rc = token_create_public_tree(sess->hContext, newpin_hash))) return (CKR_FUNCTION_FAILED); nv_token_data->token_info.flags &= ~(CKF_SO_PIN_TO_BE_CHANGED); return (save_token_data(nv_token_data)); } if (memcmp(current_so_pin_sha, oldpin_hash, SHA1_DIGEST_LENGTH)) return (CKR_PIN_INCORRECT); if ((rc = check_pin_properties(CKU_SO, newpin_hash, ulNewPinLen))) return (rc); /* change auth on the SO's leaf key */ if (tss_change_auth(sess->hContext, hPublicLeafKey, hPublicRootKey, publicLeafKeyUUID, publicRootKeyUUID, newpin_hash)) return (CKR_FUNCTION_FAILED); } else { rc = CKR_SESSION_READ_ONLY; } return (rc); } /* only called at token init time */ CK_RV token_specific_verify_so_pin(TSS_HCONTEXT hContext, CK_CHAR_PTR pPin, CK_ULONG ulPinLen) { CK_BYTE hash_sha[SHA1_DIGEST_LENGTH]; CK_RV rc; TSS_RESULT result; TSS_HKEY hSRK; if ((rc = compute_sha(pPin, ulPinLen, hash_sha))) { return (CKR_FUNCTION_FAILED); } if ((rc = token_load_srk(hContext, &hSRK))) { return (CKR_FUNCTION_FAILED); } /* * TRYME INSTEAD: * - find publicRootKeyUUID * - Load publicRootKey by UUID (SRK parent) * - find publicLeafKeyUUID * - Load publicLeafKey by UUID (publicRootKey parent) * - set password policy on publicLeafKey */ if (local_uuid_is_null(&publicRootKeyUUID) && find_uuid(TPMTOK_PUBLIC_ROOT_KEY_ID, &publicRootKeyUUID)) { /* * The SO hasn't set their PIN yet, compare the * login pin with the hard-coded value. */ if (memcmp(default_so_pin_sha, hash_sha, SHA1_DIGEST_LENGTH)) { return (CKR_PIN_INCORRECT); } return (CKR_OK); } result = Tspi_Context_GetKeyByUUID(hContext, TSS_PS_TYPE_USER, publicRootKeyUUID, &hPublicRootKey); if (result) return (CKR_FUNCTION_FAILED); result = Tspi_Key_LoadKey(hPublicRootKey, hSRK); if (result) return (CKR_FUNCTION_FAILED); if (local_uuid_is_null(&publicLeafKeyUUID) && find_uuid(TPMTOK_PUBLIC_LEAF_KEY_ID, &publicLeafKeyUUID)) return (CKR_FUNCTION_FAILED); result = Tspi_Context_GetKeyByUUID(hContext, TSS_PS_TYPE_USER, publicLeafKeyUUID, &hPublicLeafKey); if (result) return (CKR_FUNCTION_FAILED); result = tss_assign_secret_key_policy(hContext, TSS_POLICY_USAGE, hPublicLeafKey, hash_sha); if (result) return (CKR_FUNCTION_FAILED); result = Tspi_Key_LoadKey(hPublicLeafKey, hPublicRootKey); if (result) return (CKR_FUNCTION_FAILED); /* If the hash given is wrong, the verify will fail */ if ((rc = token_verify_pin(hContext, hPublicLeafKey))) { return (rc); } return (CKR_OK); } CK_RV token_specific_final(TSS_HCONTEXT hContext) { if (hPublicRootKey != NULL_HKEY) { Tspi_Context_CloseObject(hContext, hPublicRootKey); hPublicRootKey = NULL_HKEY; } if (hPublicLeafKey != NULL_HKEY) { Tspi_Context_CloseObject(hContext, hPublicLeafKey); hPublicLeafKey = NULL_HKEY; } if (hPrivateRootKey != NULL_HKEY) { Tspi_Context_CloseObject(hContext, hPrivateRootKey); hPrivateRootKey = NULL_HKEY; } if (hPrivateLeafKey != NULL_HKEY) { Tspi_Context_CloseObject(hContext, hPrivateLeafKey); hPrivateLeafKey = NULL_HKEY; } return (CKR_OK); } /* * Wrap the 20 bytes of auth data and store in an attribute of the two * keys. */ static CK_RV token_wrap_auth_data(TSS_HCONTEXT hContext, CK_BYTE *authData, TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl) { CK_RV rc; CK_ATTRIBUTE *new_attr; TSS_RESULT ret; TSS_HKEY hParentKey; TSS_HENCDATA hEncData; BYTE *blob; UINT32 blob_size; if ((hPrivateLeafKey == NULL_HKEY) && (hPublicLeafKey == NULL_HKEY)) { return (CKR_FUNCTION_FAILED); } else if (hPublicLeafKey != NULL_HKEY) { hParentKey = hPublicLeafKey; } else { hParentKey = hPrivateLeafKey; } /* create the encrypted data object */ if ((ret = Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, &hEncData))) { stlogit("Tspi_Context_CreateObject: 0x%0x - %s", ret, Trspi_Error_String(ret)); return (CKR_FUNCTION_FAILED); } if ((ret = Tspi_Data_Bind(hEncData, hParentKey, SHA1_DIGEST_LENGTH, authData))) { stlogit("Tspi_Data_Bind: 0x%0x - %s", ret, Trspi_Error_String(ret)); return (CKR_FUNCTION_FAILED); } /* pull the encrypted data out of the encrypted data object */ if ((ret = Tspi_GetAttribData(hEncData, TSS_TSPATTRIB_ENCDATA_BLOB, TSS_TSPATTRIB_ENCDATABLOB_BLOB, &blob_size, &blob))) { stlogit("Tspi_SetAttribData: 0x%0x - %s", ret, Trspi_Error_String(ret)); return (CKR_FUNCTION_FAILED); } if ((rc = build_attribute(CKA_ENC_AUTHDATA, blob, blob_size, &new_attr))) { return (rc); } (void) template_update_attribute(publ_tmpl, new_attr); if ((rc = build_attribute(CKA_ENC_AUTHDATA, blob, blob_size, &new_attr))) { return (rc); } (void) template_update_attribute(priv_tmpl, new_attr); return (rc); } static CK_RV token_unwrap_auth_data(TSS_HCONTEXT hContext, CK_BYTE *encAuthData, CK_ULONG encAuthDataLen, TSS_HKEY hKey, BYTE **authData) { TSS_RESULT result; TSS_HENCDATA hEncData; BYTE *buf; UINT32 buf_size; if ((result = Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, &hEncData))) { stlogit("Tspi_Context_CreateObject: 0x%0x - %s", result, Trspi_Error_String(result)); return (CKR_FUNCTION_FAILED); } if ((result = Tspi_SetAttribData(hEncData, TSS_TSPATTRIB_ENCDATA_BLOB, TSS_TSPATTRIB_ENCDATABLOB_BLOB, encAuthDataLen, encAuthData))) { stlogit("Tspi_SetAttribData: 0x%0x - %s", result, Trspi_Error_String(result)); return (CKR_FUNCTION_FAILED); } /* unbind the data, receiving the plaintext back */ if ((result = Tspi_Data_Unbind(hEncData, hKey, &buf_size, &buf))) { stlogit("Tspi_Data_Unbind: 0x%0x - %s", result, Trspi_Error_String(result)); return (CKR_FUNCTION_FAILED); } if (buf_size != SHA1_DIGEST_LENGTH) { return (CKR_FUNCTION_FAILED); } *authData = buf; return (CKR_OK); } CK_RV token_specific_rsa_generate_keypair( TSS_HCONTEXT hContext, TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl) { CK_ATTRIBUTE *attr = NULL; CK_ULONG mod_bits = 0; CK_BBOOL flag; CK_RV rc; TSS_FLAG initFlags = 0; BYTE authHash[SHA1_DIGEST_LENGTH]; BYTE *authData = NULL; TSS_HKEY hKey = NULL_HKEY; TSS_HKEY hParentKey = NULL_HKEY; TSS_RESULT result; UINT32 ulBlobLen; BYTE *rgbBlob; /* Make sure the public exponent is usable */ if ((util_check_public_exponent(publ_tmpl))) { return (CKR_TEMPLATE_INCONSISTENT); } flag = template_attribute_find(publ_tmpl, CKA_MODULUS_BITS, &attr); if (!flag) { return (CKR_TEMPLATE_INCOMPLETE); } mod_bits = *(CK_ULONG *)attr->pValue; if ((initFlags = util_get_keysize_flag(mod_bits)) == 0) { return (CKR_KEY_SIZE_RANGE); } /* * If we're not logged in, hPrivateLeafKey and hPublicLeafKey * should be NULL. */ if ((hPrivateLeafKey == NULL_HKEY) && (hPublicLeafKey == NULL_HKEY)) { /* public session, wrap key with the PRK */ initFlags |= TSS_KEY_TYPE_LEGACY | TSS_KEY_NO_AUTHORIZATION | TSS_KEY_MIGRATABLE; if ((result = token_load_public_root_key(hContext))) { return (CKR_FUNCTION_FAILED); } hParentKey = hPublicRootKey; } else if (hPrivateLeafKey != NULL_HKEY) { /* logged in USER session */ initFlags |= TSS_KEY_TYPE_LEGACY | TSS_KEY_AUTHORIZATION | TSS_KEY_MIGRATABLE; /* get a random SHA1 hash for the auth data */ if ((rc = token_rng(hContext, authHash, SHA1_DIGEST_LENGTH))) { return (CKR_FUNCTION_FAILED); } authData = authHash; hParentKey = hPrivateRootKey; } else { /* logged in SO session */ initFlags |= TSS_KEY_TYPE_LEGACY | TSS_KEY_AUTHORIZATION | TSS_KEY_MIGRATABLE; /* get a random SHA1 hash for the auth data */ if ((rc = token_rng(hContext, authHash, SHA1_DIGEST_LENGTH))) { return (CKR_FUNCTION_FAILED); } authData = authHash; hParentKey = hPublicRootKey; } if ((result = tss_generate_key(hContext, initFlags, authData, hParentKey, &hKey))) { return (result); } if ((result = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_KEY_BLOB, TSS_TSPATTRIB_KEYBLOB_BLOB, &ulBlobLen, &rgbBlob))) { stlogit("Tspi_GetAttribData: 0x%0x - %s", result, Trspi_Error_String(result)); return (CKR_FUNCTION_FAILED); } if ((rc = build_attribute(CKA_IBM_OPAQUE, rgbBlob, ulBlobLen, &attr))) { Tspi_Context_FreeMemory(hContext, rgbBlob); return (rc); } (void) template_update_attribute(priv_tmpl, attr); if ((rc = build_attribute(CKA_IBM_OPAQUE, rgbBlob, ulBlobLen, &attr))) { Tspi_Context_FreeMemory(hContext, rgbBlob); return (rc); } (void) template_update_attribute(publ_tmpl, attr); Tspi_Context_FreeMemory(hContext, rgbBlob); /* grab the public key to put into the public key object */ if ((result = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_RSAKEY_INFO, TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, &ulBlobLen, &rgbBlob))) { stlogit("Tspi_GetAttribData: 0x%0x - %s", result, Trspi_Error_String(result)); return (result); } /* add the public key blob to the object template */ if ((rc = build_attribute(CKA_MODULUS, rgbBlob, ulBlobLen, &attr))) { Tspi_Context_FreeMemory(hContext, rgbBlob); return (rc); } (void) template_update_attribute(publ_tmpl, attr); /* add the public key blob to the object template */ if ((rc = build_attribute(CKA_MODULUS, rgbBlob, ulBlobLen, &attr))) { Tspi_Context_FreeMemory(hContext, rgbBlob); return (rc); } (void) template_update_attribute(priv_tmpl, attr); Tspi_Context_FreeMemory(hContext, rgbBlob); /* wrap the authdata and put it into an object */ if (authData != NULL) { rc = token_wrap_auth_data(hContext, authData, publ_tmpl, priv_tmpl); } return (rc); } static CK_RV token_rsa_load_key( TSS_HCONTEXT hContext, OBJECT *key_obj, TSS_HKEY *phKey) { TSS_RESULT result; TSS_HPOLICY hPolicy = NULL_HPOLICY; TSS_HKEY hParentKey; BYTE *authData = NULL; CK_ATTRIBUTE *attr; CK_RV rc; CK_OBJECT_HANDLE handle; CK_ULONG class; if (hPrivateLeafKey != NULL_HKEY) { hParentKey = hPrivateRootKey; } else { if ((result = token_load_public_root_key(hContext))) return (CKR_FUNCTION_FAILED); hParentKey = hPublicRootKey; } *phKey = 0; if (template_attribute_find(key_obj->template, CKA_CLASS, &attr) == FALSE) { return (CKR_TEMPLATE_INCOMPLETE); } class = *((CK_ULONG *)attr->pValue); rc = template_attribute_find(key_obj->template, CKA_IBM_OPAQUE, &attr); /* * A public key cannot use the OPAQUE data attribute so they * must be created in software. A private key may not yet * have its "opaque" data defined and needs to be created * and loaded so it can be used inside the TPM. */ if (class == CKO_PUBLIC_KEY || rc == FALSE) { rc = object_mgr_find_in_map2(hContext, key_obj, &handle); if (rc != CKR_OK) return (CKR_FUNCTION_FAILED); if ((rc = token_load_key(hContext, handle, hParentKey, NULL, phKey))) { return (rc); } } /* * If this is a private key, get the blob and load it in the TPM. * If it is public, the key is already loaded in software. */ if (class == CKO_PRIVATE_KEY) { /* If we already have a handle, just load it */ if (*phKey != 0) { result = Tspi_Key_LoadKey(*phKey, hParentKey); if (result) { stlogit("Tspi_Context_LoadKeyByBlob: " "0x%0x - %s", result, Trspi_Error_String(result)); return (CKR_FUNCTION_FAILED); } } else { /* try again to get the CKA_IBM_OPAQUE attr */ if ((rc = template_attribute_find(key_obj->template, CKA_IBM_OPAQUE, &attr)) == FALSE) { return (rc); } if ((result = Tspi_Context_LoadKeyByBlob(hContext, hParentKey, attr->ulValueLen, attr->pValue, phKey))) { stlogit("Tspi_Context_LoadKeyByBlob: " "0x%0x - %s", result, Trspi_Error_String(result)); return (CKR_FUNCTION_FAILED); } } } /* auth data may be required */ if (template_attribute_find(key_obj->template, CKA_ENC_AUTHDATA, &attr) == TRUE && attr) { if ((hPrivateLeafKey == NULL_HKEY) && (hPublicLeafKey == NULL_HKEY)) { return (CKR_FUNCTION_FAILED); } else if (hPublicLeafKey != NULL_HKEY) { hParentKey = hPublicLeafKey; } else { hParentKey = hPrivateLeafKey; } if ((result = token_unwrap_auth_data(hContext, attr->pValue, attr->ulValueLen, hParentKey, &authData))) { return (CKR_FUNCTION_FAILED); } if ((result = Tspi_GetPolicyObject(*phKey, TSS_POLICY_USAGE, &hPolicy))) { stlogit("Tspi_GetPolicyObject: 0x%0x - %s", result, Trspi_Error_String(result)); return (CKR_FUNCTION_FAILED); } /* * If the policy handle returned is the same as the * context's default policy, then a new policy must * be created and assigned to the key. Otherwise, just set the * secret in the policy. */ if (hPolicy == hDefaultPolicy) { if ((result = Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_POLICY, TSS_POLICY_USAGE, &hPolicy))) { stlogit("Tspi_Context_CreateObject: " "0x%0x - %s", result, Trspi_Error_String(result)); return (CKR_FUNCTION_FAILED); } if ((result = Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_SHA1, SHA1_DIGEST_LENGTH, authData))) { stlogit("Tspi_Policy_SetSecret: " "0x%0x - %s", result, Trspi_Error_String(result)); return (CKR_FUNCTION_FAILED); } if ((result = Tspi_Policy_AssignToObject(hPolicy, *phKey))) { stlogit("Tspi_Policy_AssignToObject: " "0x%0x - %s", result, Trspi_Error_String(result)); return (CKR_FUNCTION_FAILED); } } else if ((result = Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_SHA1, SHA1_DIGEST_LENGTH, authData))) { stlogit("Tspi_Policy_SetSecret: 0x%0x - %s", result, Trspi_Error_String(result)); return (CKR_FUNCTION_FAILED); } Tspi_Context_FreeMemory(hContext, authData); } return (CKR_OK); } CK_RV tpm_decrypt_data( TSS_HCONTEXT hContext, TSS_HKEY hKey, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len) { TSS_RESULT result; TSS_HENCDATA hEncData = NULL_HENCDATA; UINT32 buf_size = 0, modLen; BYTE *buf = NULL, *modulus = NULL; CK_ULONG chunklen, remain, outlen; /* push the data into the encrypted data object */ if ((result = Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, &hEncData))) { stlogit("Tspi_Context_CreateObject: 0x%0x - %s", result, Trspi_Error_String(result)); return (CKR_FUNCTION_FAILED); } /* * Figure out the modulus size so we can break the data * into smaller chunks if necessary. */ if ((result = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_RSAKEY_INFO, TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, &modLen, &modulus))) { stlogit("Tspi_GetAttribData: 0x%0x - %s", result, Trspi_Error_String(result)); return (result); } /* we don't need the actual modulus */ Tspi_Context_FreeMemory(hContext, modulus); chunklen = (in_data_len > modLen ? modLen : in_data_len); remain = in_data_len; outlen = 0; while (remain > 0) { if ((result = Tspi_SetAttribData(hEncData, TSS_TSPATTRIB_ENCDATA_BLOB, TSS_TSPATTRIB_ENCDATABLOB_BLOB, chunklen, in_data))) { stlogit("Tspi_SetAttribData: 0x%0x - %s", result, Trspi_Error_String(result)); return (CKR_FUNCTION_FAILED); } /* unbind the data, receiving the plaintext back */ if ((result = Tspi_Data_Unbind(hEncData, hKey, &buf_size, &buf))) { stlogit("Tspi_Data_Unbind: 0x%0x - %s", result, Trspi_Error_String(result)); return (CKR_FUNCTION_FAILED); } if (*out_data_len < buf_size + outlen) { Tspi_Context_FreeMemory(hContext, buf); return (CKR_BUFFER_TOO_SMALL); } (void) memcpy(out_data + outlen, buf, buf_size); outlen += buf_size; in_data += chunklen; remain -= chunklen; Tspi_Context_FreeMemory(hContext, buf); if (chunklen > remain) chunklen = remain; } *out_data_len = outlen; return (CKR_OK); } CK_RV token_specific_rsa_decrypt( TSS_HCONTEXT hContext, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, OBJECT * key_obj) { CK_RV rc; TSS_HKEY hKey; if ((rc = token_rsa_load_key(hContext, key_obj, &hKey))) { return (rc); } rc = tpm_decrypt_data(hContext, hKey, in_data, in_data_len, out_data, out_data_len); return (rc); } CK_RV token_specific_rsa_verify( TSS_HCONTEXT hContext, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * sig, CK_ULONG sig_len, OBJECT * key_obj) { TSS_RESULT result; TSS_HHASH hHash; TSS_HKEY hKey; CK_RV rc; if ((rc = token_rsa_load_key(hContext, key_obj, &hKey))) { return (rc); } /* Create the hash object we'll use to sign */ if ((result = Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_HASH, TSS_HASH_OTHER, &hHash))) { stlogit("Tspi_Context_CreateObject: 0x%0x - %s", result, Trspi_Error_String(result)); return (CKR_FUNCTION_FAILED); } /* Insert the data into the hash object */ if ((result = Tspi_Hash_SetHashValue(hHash, in_data_len, in_data))) { stlogit("Tspi_Hash_SetHashValue: 0x%0x - %s", result, Trspi_Error_String(result)); return (CKR_FUNCTION_FAILED); } /* Verify */ result = Tspi_Hash_VerifySignature(hHash, hKey, sig_len, sig); if (result != TSS_SUCCESS && TPMTOK_TSS_ERROR_CODE(result) != TSS_E_FAIL) { stlogit("Tspi_Hash_VerifySignature: 0x%0x - %s", result, Trspi_Error_String(result)); } if (TPMTOK_TSS_ERROR_CODE(result) == TSS_E_FAIL) { rc = CKR_SIGNATURE_INVALID; } else { rc = CKR_OK; } return (rc); } CK_RV token_specific_rsa_sign( TSS_HCONTEXT hContext, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, OBJECT * key_obj) { TSS_RESULT result; TSS_HHASH hHash; BYTE *sig; UINT32 sig_len; TSS_HKEY hKey; CK_RV rc; if ((rc = token_rsa_load_key(hContext, key_obj, &hKey))) { return (rc); } /* Create the hash object we'll use to sign */ if ((result = Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_HASH, TSS_HASH_OTHER, &hHash))) { stlogit("Tspi_Context_CreateObject: 0x%0x - %s", result, Trspi_Error_String(result)); return (CKR_FUNCTION_FAILED); } /* Insert the data into the hash object */ if ((result = Tspi_Hash_SetHashValue(hHash, in_data_len, in_data))) { stlogit("Tspi_Hash_SetHashValue: 0x%0x - %s", result, Trspi_Error_String(result)); return (CKR_FUNCTION_FAILED); } /* Sign */ if ((result = Tspi_Hash_Sign(hHash, hKey, &sig_len, &sig))) { stlogit("Tspi_Hash_Sign: 0x%0x - %s", result, Trspi_Error_String(result)); return (CKR_DATA_LEN_RANGE); } if (sig_len > *out_data_len) { Tspi_Context_FreeMemory(hContext, sig); return (CKR_BUFFER_TOO_SMALL); } (void) memcpy(out_data, sig, sig_len); *out_data_len = sig_len; Tspi_Context_FreeMemory(hContext, sig); return (CKR_OK); } CK_RV tpm_encrypt_data( TSS_HCONTEXT hContext, TSS_HKEY hKey, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { TSS_RESULT result; TSS_HENCDATA hEncData; BYTE *dataBlob, *modulus; UINT32 dataBlobSize, modLen; CK_ULONG chunklen, remain; CK_ULONG outlen; UINT32 keyusage, scheme, maxsize; if ((result = Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, &hEncData))) { stlogit("Tspi_Context_CreateObject: 0x%0x - %s", result, Trspi_Error_String(result)); return (CKR_FUNCTION_FAILED); } /* * Figure out the modulus size so we can break the data * into smaller chunks if necessary. */ if ((result = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_RSAKEY_INFO, TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, &modLen, &modulus))) { stlogit("Tspi_GetAttribData: 0x%0x - %s", result, Trspi_Error_String(result)); return (result); } /* we don't need the actual modulus */ Tspi_Context_FreeMemory(hContext, modulus); /* * According to TSS spec for Tspi_Data_Bind (4.3.4.21.5), * Max input data size varies depending on the key type and * encryption scheme. */ if ((result = Tspi_GetAttribUint32(hKey, TSS_TSPATTRIB_KEY_INFO, TSS_TSPATTRIB_KEYINFO_USAGE, &keyusage))) { stlogit("Cannot find USAGE: %s\n", Trspi_Error_String(result)); return (result); } if ((result = Tspi_GetAttribUint32(hKey, TSS_TSPATTRIB_KEY_INFO, TSS_TSPATTRIB_KEYINFO_ENCSCHEME, &scheme))) { stlogit("Cannot find ENCSCHEME: %s\n", Trspi_Error_String(result)); return (result); } switch (scheme) { case TSS_ES_RSAESPKCSV15: if (keyusage == TSS_KEYUSAGE_BIND) maxsize = 16; else /* legacy */ maxsize = 11; break; case TSS_ES_RSAESOAEP_SHA1_MGF1: maxsize = 47; break; default: maxsize = 0; } modLen -= maxsize; chunklen = (in_data_len > modLen ? modLen : in_data_len); remain = in_data_len; outlen = 0; while (remain > 0) { if ((result = Tspi_Data_Bind(hEncData, hKey, chunklen, in_data))) { stlogit("Tspi_Data_Bind: 0x%0x - %s", result, Trspi_Error_String(result)); return (CKR_FUNCTION_FAILED); } if ((result = Tspi_GetAttribData(hEncData, TSS_TSPATTRIB_ENCDATA_BLOB, TSS_TSPATTRIB_ENCDATABLOB_BLOB, &dataBlobSize, &dataBlob))) { stlogit("Tspi_GetAttribData: 0x%0x - %s", result, Trspi_Error_String(result)); return (CKR_FUNCTION_FAILED); } if (outlen + dataBlobSize > *out_data_len) { Tspi_Context_FreeMemory(hContext, dataBlob); return (CKR_DATA_LEN_RANGE); } (void) memcpy(out_data + outlen, dataBlob, dataBlobSize); outlen += dataBlobSize; in_data += chunklen; remain -= chunklen; if (chunklen > remain) chunklen = remain; Tspi_Context_FreeMemory(hContext, dataBlob); } *out_data_len = outlen; return (CKR_OK); } CK_RV token_specific_rsa_encrypt( TSS_HCONTEXT hContext, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, OBJECT * key_obj) { TSS_HKEY hKey; CK_RV rc; if ((rc = token_rsa_load_key(hContext, key_obj, &hKey))) { return (rc); } rc = tpm_encrypt_data(hContext, hKey, in_data, in_data_len, out_data, out_data_len); return (rc); } /* * RSA Verify Recover * * Public key crypto is done in software, not by the TPM. * We use libsoftcrypto and perform the RSA operations ourselves similar * to how pkcs11_softtoken performs the operation. */ CK_RV token_specific_rsa_verify_recover( TSS_HCONTEXT hContext, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen, OBJECT *key_obj) { TSS_HKEY hKey; TSS_RESULT result; CK_RV rc; BYTE *modulus; UINT32 modLen; RSAbytekey rsa = { 0 }; uchar_t exp[] = { 0x01, 0x00, 0x01 }; CK_BYTE plain_data[MAX_RSA_KEYLENGTH]; size_t data_len; if ((rc = token_rsa_load_key(hContext, key_obj, &hKey))) { return (rc); } if ((result = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_RSAKEY_INFO, TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, &modLen, &modulus))) { stlogit("Tspi_GetAttribData: 0x%0x - %s", result, Trspi_Error_String(result)); return (CKR_FUNCTION_FAILED); } if (ulSignatureLen != modLen) { rc = CKR_SIGNATURE_LEN_RANGE; goto end; } rsa.modulus = modulus; rsa.modulus_bits = CRYPTO_BYTES2BITS(modLen); rsa.pubexpo = exp; rsa.pubexpo_bytes = sizeof (exp); if ((rc = rsa_encrypt(&rsa, pSignature, modLen, plain_data)) != CKR_OK) goto end; data_len = modLen; if ((rc = pkcs1_decode(PKCS1_VERIFY, plain_data, &data_len)) != CKR_OK) goto end; (void) memcpy(pData, &plain_data[modLen - data_len], data_len); *pulDataLen = data_len; end: Tspi_Context_FreeMemory(hContext, modulus); return (rc); } /* * The Initial Developer of the Original Code is International * Business Machines Corporation. Portions created by IBM * Corporation are Copyright (C) 2005 International Business * Machines Corporation. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the Common Public License as published by * IBM Corporation; either version 1 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * Common Public License for more details. * * You should have received a copy of the Common Public License * along with this program; if not, a copy can be viewed at * http://www.opensource.org/licenses/cpl1.0.php. */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _TPMTOK_DEFS_H #define _TPMTOK_DEFS_H /* TSS key type helper */ #define TPMTOK_TSS_KEY_TYPE_MASK 0x000000F0 #define TPMTOK_TSS_KEY_TYPE(x) (x & TPMTOK_TSS_KEY_TYPE_MASK) #define TPMTOK_TSS_KEY_MIG_TYPE(x) (x & TSS_KEY_MIGRATABLE) #define TPMTOK_TSS_MAX_ERROR 0x00000FFF #define TPMTOK_TSS_ERROR_CODE(x) (x & TPMTOK_TSS_MAX_ERROR) /* key types in the TPM token */ #define TPMTOK_PRIVATE_ROOT_KEY 1 #define TPMTOK_PRIVATE_LEAF_KEY 2 #define TPMTOK_PUBLIC_ROOT_KEY 3 #define TPMTOK_PUBLIC_LEAF_KEY 4 /* key identifiers for the PKCS#11 objects */ #define TPMTOK_PRIVATE_ROOT_KEY_ID "PRIVATE_ROOT_KEY" #define TPMTOK_PRIVATE_LEAF_KEY_ID "PRIVATE_LEAF_KEY" #define TPMTOK_PUBLIC_ROOT_KEY_ID "PUBLIC_ROOT_KEY" #define TPMTOK_PUBLIC_LEAF_KEY_ID "PUBLIC_LEAF_KEY" #define NULL_HKEY 0 #define NULL_HENCDATA 0 #define NULL_HPOLICY 0 #define NULL_HCONTEXT 0 #define NULL_HPCRS 0 #define LOG(priority, fmt, ...) \ {\ openlog("tpmtoken", LOG_NDELAY|LOG_PID, LOG_USER);\ syslog(priority, "%s " fmt, __FILE__, ##__VA_ARGS__);\ } #endif /* _TPMTOK_DEFS_H */ /* * The Initial Developer of the Original Code is International * Business Machines Corporation. Portions created by IBM * Corporation are Copyright(C) 2005 International Business * Machines Corporation. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the Common Public License as published by * IBM Corporation; either version 1 of the License, or(at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * Common Public License for more details. * * You should have received a copy of the Common Public License * along with this program; if not, a copy can be viewed at * http://www.opensource.org/licenses/cpl1.0.php. */ /* (C) COPYRIGHT International Business Machines Corp. 2001, 2002, 2005 */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * Copyright 2018 Jason King */ #ifndef _TPMTOK_INT_H #define _TPMTOK_INT_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define VERSION_MAJOR 2 #define VERSION_MINOR 1 #define MAX_SESSION_COUNT 64 #define MAX_PIN_LEN 256 #define MIN_PIN_LEN 1 #define MAX_SLOT_ID 10 #ifndef MIN #define MIN(a, b) ((a) < (b) ? (a) : (b)) #endif #define MODE_COPY (1 << 0) #define MODE_CREATE (1 << 1) #define MODE_KEYGEN (1 << 2) #define MODE_MODIFY (1 << 3) #define MODE_DERIVE (1 << 4) #define MODE_UNWRAP (1 << 5) // RSA block formatting types // #define PKCS_BT_1 1 #define PKCS_BT_2 2 #define OP_ENCRYPT_INIT 1 #define OP_DECRYPT_INIT 2 #define OP_WRAP 3 #define OP_UNWRAP 4 #define OP_SIGN_INIT 5 #define OP_VERIFY_INIT 6 enum { STATE_INVALID = 0, STATE_ENCR, STATE_DECR, STATE_DIGEST, STATE_SIGN, STATE_VERIFY }; #define SHA1_BLOCK_SIZE 64 #define SHA1_BLOCK_SIZE_MASK (SHA1_BLOCK_SIZE - 1) #define RSA_BLOCK_SIZE 256 #ifndef PATH_MAX #define PATH_MAX MAXPATHLEN #endif #ifndef PACK_DATA #define PACK_DATA #endif #define MD5_BLOCK_SIZE 64 #define DSA_SIGNATURE_SIZE 40 #define DEFAULT_SO_PIN "87654321" typedef enum { ALL = 1, PRIVATE, PUBLIC } SESS_OBJ_TYPE; typedef struct _DL_NODE { struct _DL_NODE *next; struct _DL_NODE *prev; void *data; } DL_NODE; #define TOKEN_DATA_FILE "token.dat" #define TOKEN_OBJ_DIR "objects" #define TOKEN_OBJ_INDEX_FILE "obj.idx" #define TPMTOK_UUID_INDEX_FILENAME "uuids.idx" /* * Filenames used to store migration data. */ #define SO_MAKEY_FILENAME "so_makey.dat" #define USER_MAKEY_FILENAME "user_makey.dat" #define SO_KEYBLOB_FILENAME "so_blob.dat" #define USER_KEYBLOB_FILENAME "user_blob.dat" #define __FUNCTION__ __func__ // // Both of the strings below have a length of 32 chars and must be // padded with spaces, and non - null terminated. // #define PKW_CRYPTOKI_VERSION_MAJOR 2 #define PKW_CRYPTOKI_VERSION_MINOR 1 #define PKW_CRYPTOKI_MANUFACTURER "Sun Microsystems, Inc. " #define PKW_CRYPTOKI_LIBDESC "PKCS#11 Interface for TPM " #define PKW_CRYPTOKI_LIB_VERSION_MAJOR 1 #define PKW_CRYPTOKI_LIB_VERSION_MINOR 0 #define PKW_MAX_DEVICES 10 #define MAX_TOK_OBJS 2048 #define NUMBER_SLOTS_MANAGED 1 #define TPM_SLOTID 1 /* * CKA_HIDDEN will be used to filter return results on * a C_FindObjects call. Used for objects internal to the * TPM token for management */ /* custom attributes for the TPM token */ #define CKA_HIDDEN CKA_VENDOR_DEFINED + 0x01 #define CKA_IBM_OPAQUE CKA_VENDOR_DEFINED + 0x02 /* * CKA_ENC_AUTHDATA will be used to store the encrypted SHA-1 * hashes of auth data passed in for TPM keys. The authdata * will be encrypted using either the public * leaf key or the private leaf key */ #define CKA_ENC_AUTHDATA CKA_VENDOR_DEFINED + 0x03 /* custom return codes for the TPM token */ #define CKR_KEY_NOT_FOUND CKR_VENDOR_DEFINED + 0x01 #define CKR_FILE_NOT_FOUND CKR_VENDOR_DEFINED + 0x02 typedef struct { CK_SLOT_ID slotID; CK_SESSION_HANDLE sessionh; } ST_SESSION_T; typedef ST_SESSION_T ST_SESSION_HANDLE; typedef struct { void *Previous; void *Next; CK_SLOT_ID SltId; CK_SESSION_HANDLE RealHandle; } Session_Struct_t; typedef Session_Struct_t *SessStructP; typedef struct { pid_t Pid; pthread_mutex_t ProcMutex; Session_Struct_t *SessListBeg; Session_Struct_t *SessListEnd; pthread_mutex_t SessListMutex; } API_Proc_Struct_t; enum { PRF_DUMMYFUNCTION = 1, PRF_FCVFUNCTION, PRF_INITIALIZE, PRF_FINALIZE, PRF_GETINFO, PRF_GETFUNCTIONLIST, PRF_GETSLOTLIST, PRF_GETSLOTINFO, PRF_GETTOKENINFO, PRF_GETMECHLIST, PRF_GETMECHINFO, PRF_INITTOKEN, PRF_INITPIN, PRF_SETPIN, PRF_OPENSESSION, PRF_CLOSESESSION, PRF_CLOSEALLSESSIONS, PRF_GETSESSIONINFO, PRF_GETOPERATIONSTATE, PRF_SETOPERATIONSTATE, PRF_LOGIN, PRF_LOGOUT, PRF_CREATEOBJECT, PRF_COPYOBJECT, PRF_DESTROYOBJECT, PRF_GETOBJECTSIZE, PRF_GETATTRIBUTEVALUE, PRF_SETATTRIBUTEVALUE, PRF_FINDOBJECTSINIT, PRF_FINDOBJECTS, PRF_FINDOBJECTSFINAL, PRF_ENCRYPTINIT, PRF_ENCRYPT, PRF_ENCRYPTUPDATE, PRF_ENCRYPTFINAL, PRF_DECRYPTINIT, PRF_DECRYPT, PRF_DECRYPTUPDATE, PRF_DECRYPTFINAL, PRF_DIGESTINIT, PRF_DIGEST, PRF_DIGESTUPDATE, PRF_DIGESTKEY, PRF_DIGESTFINAL, PRF_SIGNINIT, PRF_SIGN, PRF_SIGNUPDATE, PRF_SIGNFINAL, PRF_SIGNRECOVERINIT, PRF_SIGNRECOVER, PRF_VERIFYINIT, PRF_VERIFY, PRF_VERIFYUPDATE, PRF_VERIFYFINAL, PRF_VERIFYRECOVERINIT, PRF_VERIFYRECOVER, PRF_GENKEY, PRF_GENKEYPAIR, PRF_WRAPKEY, PRF_UNWRAPKEY, PRF_DERIVEKEY, PRF_GENRND, PRF_LASTENTRY }; typedef struct _ENCR_DECR_CONTEXT { CK_OBJECT_HANDLE key; CK_MECHANISM mech; CK_BYTE *context; CK_ULONG context_len; CK_BBOOL multi; CK_BBOOL active; } ENCR_DECR_CONTEXT; typedef struct _DIGEST_CONTEXT { CK_MECHANISM mech; union { MD5_CTX *md5ctx; SHA1_CTX *sha1ctx; void *ref; /* reference ptr for the union */ } context; CK_ULONG context_len; CK_BBOOL multi; CK_BBOOL active; } DIGEST_CONTEXT; typedef struct _SIGN_VERIFY_CONTEXT { CK_OBJECT_HANDLE key; CK_MECHANISM mech; // current sign mechanism void *context; // temporary work area CK_ULONG context_len; CK_BBOOL multi; // is this a multi - part operation? CK_BBOOL recover; // are we in recover mode? CK_BBOOL active; } SIGN_VERIFY_CONTEXT; typedef struct _SESSION { CK_SESSION_HANDLE handle; CK_SESSION_INFO session_info; CK_OBJECT_HANDLE *find_list; // array of CK_OBJECT_HANDLE CK_ULONG find_count; // # handles in the list CK_ULONG find_len; // max # of handles in the list CK_ULONG find_idx; // current position CK_BBOOL find_active; ENCR_DECR_CONTEXT encr_ctx; ENCR_DECR_CONTEXT decr_ctx; DIGEST_CONTEXT digest_ctx; SIGN_VERIFY_CONTEXT sign_ctx; SIGN_VERIFY_CONTEXT verify_ctx; TSS_HCONTEXT hContext; } SESSION; typedef struct _TEMPLATE { DL_NODE *attribute_list; } TEMPLATE; typedef struct _OBJECT { CK_OBJECT_CLASS class; CK_BYTE name[8]; // for token objects SESSION *session; // creator; only for session objects TEMPLATE *template; CK_ULONG count_hi; // only significant for token objects CK_ULONG count_lo; // only significant for token objects CK_ULONG index; } OBJECT; typedef struct _OBJECT_MAP { CK_OBJECT_HANDLE handle; CK_BBOOL is_private; CK_BBOOL is_session_obj; SESSION *session; OBJECT *ptr; } OBJECT_MAP; typedef struct _ATTRIBUTE_PARSE_LIST { CK_ATTRIBUTE_TYPE type; void *ptr; CK_ULONG len; CK_BBOOL found; } ATTRIBUTE_PARSE_LIST; typedef struct _OP_STATE_DATA { CK_STATE session_state; CK_ULONG active_operation; CK_ULONG data_len; } OP_STATE_DATA; typedef struct _TWEAK_VEC { int allow_key_mods; } TWEAK_VEC; typedef struct _TOKEN_DATA { CK_TOKEN_INFO token_info; CK_BYTE user_pin_sha[SHA1_DIGEST_LENGTH]; CK_BYTE so_pin_sha[SHA1_DIGEST_LENGTH]; CK_BYTE next_token_object_name[8]; TWEAK_VEC tweak_vector; } TOKEN_DATA; typedef struct _RSA_DIGEST_CONTEXT { DIGEST_CONTEXT hash_context; CK_BBOOL flag; } RSA_DIGEST_CONTEXT; typedef struct _MECH_LIST_ELEMENT { CK_MECHANISM_TYPE mech_type; CK_MECHANISM_INFO mech_info; } MECH_LIST_ELEMENT; struct mech_list_item; struct mech_list_item { struct mech_list_item *next; MECH_LIST_ELEMENT element; }; struct mech_list_item * find_mech_list_item_for_type(CK_MECHANISM_TYPE type, struct mech_list_item *head); typedef struct _TOK_OBJ_ENTRY { CK_BBOOL deleted; char name[8]; CK_ULONG count_lo; CK_ULONG count_hi; } TOK_OBJ_ENTRY; typedef struct _LW_SHM_TYPE { pthread_mutex_t mutex; TOKEN_DATA nv_token_data; CK_ULONG num_priv_tok_obj; CK_ULONG num_publ_tok_obj; CK_BBOOL priv_loaded; CK_BBOOL publ_loaded; CK_BBOOL token_available; TOK_OBJ_ENTRY publ_tok_objs[ MAX_TOK_OBJS ]; TOK_OBJ_ENTRY priv_tok_objs[ MAX_TOK_OBJS ]; } LW_SHM_TYPE; typedef unsigned int CK_ULONG_32; typedef CK_ULONG_32 CK_OBJECT_CLASS_32; typedef CK_ULONG_32 CK_ATTRIBUTE_TYPE_32; typedef struct CK_ATTRIBUTE_32 { CK_ATTRIBUTE_TYPE_32 type; CK_ULONG_32 pValue; CK_ULONG_32 ulValueLen; } CK_ATTRIBUTE_32; char *get_tpm_keystore_path(); struct messages { char *msg; }; struct token_specific_struct { CK_BYTE token_debug_tag[MAXPATHLEN]; CK_RV (*t_init)(char *, CK_SLOT_ID, TSS_HCONTEXT *); int (*t_slot2local)(); CK_RV (*t_rng)(TSS_HCONTEXT, CK_BYTE *, CK_ULONG); CK_RV (*t_session)(CK_SLOT_ID); CK_RV (*t_final)(TSS_HCONTEXT); CK_RV (*t_rsa_decrypt)(TSS_HCONTEXT, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *, OBJECT *); CK_RV (*t_rsa_encrypt)( TSS_HCONTEXT, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *, OBJECT *); CK_RV (*t_rsa_sign)(TSS_HCONTEXT, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *, OBJECT *); CK_RV (*t_rsa_verify)(TSS_HCONTEXT, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG, OBJECT *); CK_RV (*t_rsa_generate_keypair)(TSS_HCONTEXT, TEMPLATE *, TEMPLATE *); CK_RV (*t_sha_init)(DIGEST_CONTEXT *); CK_RV (*t_sha_update)( DIGEST_CONTEXT *, CK_BYTE *, CK_ULONG); CK_RV (*t_sha_final)( DIGEST_CONTEXT *, CK_BYTE *, CK_ULONG *); CK_RV (*t_login)(TSS_HCONTEXT, CK_USER_TYPE, CK_BYTE *, CK_ULONG); CK_RV (*t_logout)(TSS_HCONTEXT); CK_RV (*t_init_pin)(TSS_HCONTEXT, CK_BYTE *, CK_ULONG); CK_RV (*t_set_pin)(ST_SESSION_HANDLE, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG); CK_RV (*t_verify_so_pin)(TSS_HCONTEXT, CK_BYTE *, CK_ULONG); }; typedef struct token_specific_struct token_spec_t; /* * Global Variables */ extern void copy_slot_info(CK_SLOT_ID, CK_SLOT_INFO_PTR); extern struct messages err_msg[]; extern token_spec_t token_specific; extern CK_BBOOL initialized; extern char *card_function_names[]; extern char *total_function_names[]; extern MECH_LIST_ELEMENT mech_list[]; extern CK_ULONG mech_list_len; extern pthread_mutex_t native_mutex; extern void *xproclock; extern pthread_mutex_t pkcs_mutex, obj_list_mutex, sess_list_mutex, login_mutex; extern DL_NODE *sess_list; extern DL_NODE *sess_obj_list; extern DL_NODE *publ_token_obj_list; extern DL_NODE *priv_token_obj_list; extern DL_NODE *object_map; extern CK_BYTE so_pin_md5[MD5_DIGEST_LENGTH]; extern CK_BYTE user_pin_md5[MD5_DIGEST_LENGTH]; extern CK_BYTE default_user_pin_sha[SHA1_DIGEST_LENGTH]; extern CK_BYTE default_so_pin_sha[SHA1_DIGEST_LENGTH]; extern CK_BYTE default_so_pin_md5[MD5_DIGEST_LENGTH]; extern LW_SHM_TYPE *global_shm; extern TOKEN_DATA *nv_token_data; extern CK_ULONG next_object_handle; extern CK_ULONG next_session_handle; extern CK_STATE global_login_state; extern CK_BYTE ber_AlgIdRSAEncryption[]; extern CK_ULONG ber_AlgIdRSAEncryptionLen; extern CK_BYTE ber_rsaEncryption[]; extern CK_ULONG ber_rsaEncryptionLen; extern CK_BYTE ber_idDSA[]; extern CK_ULONG ber_idDSALen; extern CK_BYTE ber_md5WithRSAEncryption[]; extern CK_ULONG ber_md5WithRSAEncryptionLen; extern CK_BYTE ber_sha1WithRSAEncryption[]; extern CK_ULONG ber_sha1WithRSAEncryptionLen; extern CK_BYTE ber_AlgMd5[]; extern CK_ULONG ber_AlgMd5Len; extern CK_BYTE ber_AlgSha1[]; extern CK_ULONG ber_AlgSha1Len; extern CK_C_INITIALIZE_ARGS cinit_args; /* * Function Prototypes */ void *attach_shared_memory(); void detach_shared_memory(char *); int API_Initialized(); void Terminate_All_Process_Sessions(); int API_Register(); void API_UnRegister(); void CreateXProcLock(void *); int XProcLock(void *); int XProcUnLock(void *); void loginit(); void logterm(); void logit(int, char *, ...); void AddToSessionList(Session_Struct_t *); void RemoveFromSessionList(Session_Struct_t *); int Valid_Session(Session_Struct_t *, ST_SESSION_T *); CK_BBOOL pin_expired(CK_SESSION_INFO *, CK_FLAGS); CK_BBOOL pin_locked(CK_SESSION_INFO *, CK_FLAGS); void set_login_flags(CK_USER_TYPE, CK_FLAGS *); extern void init_slot_info(TOKEN_DATA *); CK_RV update_migration_data(TSS_HCONTEXT, TSS_HKEY, TSS_HKEY, char *, char *, BYTE *, BYTE *); CK_RV token_rng(TSS_HCONTEXT, CK_BYTE *, CK_ULONG); TSS_RESULT set_public_modulus(TSS_HCONTEXT, TSS_HKEY, unsigned long, unsigned char *); TSS_RESULT open_tss_context(TSS_HCONTEXT *); CK_RV token_get_tpm_info(TSS_HCONTEXT, TOKEN_DATA *); CK_RV clock_set_default_attributes(TEMPLATE *); CK_RV clock_check_required_attributes(TEMPLATE *, CK_ULONG); CK_RV clock_validate_attribute(TEMPLATE *, CK_ATTRIBUTE *, CK_ULONG); CK_RV counter_set_default_attributes(TEMPLATE *); CK_RV counter_check_required_attributes(TEMPLATE *, CK_ULONG); CK_RV counter_validate_attribute(TEMPLATE *, CK_ATTRIBUTE *, CK_ULONG); CK_RV compute_next_token_obj_name(CK_BYTE *, CK_BYTE *); CK_RV save_token_object(TSS_HCONTEXT, OBJECT *); CK_RV save_public_token_object(OBJECT *); CK_RV save_private_token_object(TSS_HCONTEXT, OBJECT *); CK_RV load_public_token_objects(void); CK_RV load_private_token_objects(TSS_HCONTEXT); CK_RV reload_token_object(TSS_HCONTEXT, OBJECT *); CK_RV delete_token_object(OBJECT *); CK_RV init_token_data(TSS_HCONTEXT, TOKEN_DATA *); CK_RV load_token_data(TSS_HCONTEXT, TOKEN_DATA *); CK_RV save_token_data(TOKEN_DATA *); void copy_slot_info(CK_SLOT_ID, CK_SLOT_INFO_PTR); CK_RV compute_sha(CK_BYTE *, CK_ULONG_32, CK_BYTE *); CK_RV parity_is_odd(CK_BYTE); CK_RV build_attribute(CK_ATTRIBUTE_TYPE, CK_BYTE *, CK_ULONG, CK_ATTRIBUTE **); CK_RV add_pkcs_padding(CK_BYTE *, UINT32, UINT32, UINT32); CK_RV strip_pkcs_padding(CK_BYTE *, UINT32, UINT32 *); CK_RV remove_leading_zeros(CK_ATTRIBUTE *); CK_RV rsa_pkcs_encrypt( SESSION *, CK_BBOOL, ENCR_DECR_CONTEXT *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *); CK_RV rsa_pkcs_decrypt(SESSION *, CK_BBOOL, ENCR_DECR_CONTEXT *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *); CK_RV rsa_pkcs_sign(SESSION *, CK_BBOOL, SIGN_VERIFY_CONTEXT *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *); CK_RV rsa_pkcs_verify(SESSION *, SIGN_VERIFY_CONTEXT *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG); CK_RV rsa_pkcs_verify_recover(SESSION *, CK_BBOOL, SIGN_VERIFY_CONTEXT *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *); CK_RV rsa_hash_pkcs_sign(SESSION *, CK_BBOOL, SIGN_VERIFY_CONTEXT *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *); CK_RV rsa_hash_pkcs_verify(SESSION *, SIGN_VERIFY_CONTEXT *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG); CK_RV rsa_hash_pkcs_sign_update(SESSION *, SIGN_VERIFY_CONTEXT *, CK_BYTE *, CK_ULONG); CK_RV rsa_hash_pkcs_verify_update(SESSION *, SIGN_VERIFY_CONTEXT *, CK_BYTE *, CK_ULONG); CK_RV rsa_hash_pkcs_sign_final(SESSION *, CK_BBOOL, SIGN_VERIFY_CONTEXT *, CK_BYTE *, CK_ULONG *); CK_RV rsa_hash_pkcs_verify_final(SESSION *, SIGN_VERIFY_CONTEXT *, CK_BYTE *, CK_ULONG); CK_RV ckm_rsa_key_pair_gen(TSS_HCONTEXT, TEMPLATE *, TEMPLATE *); CK_RV sha1_hash(SESSION *, CK_BBOOL, DIGEST_CONTEXT *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *); CK_RV sha1_hmac_sign(SESSION *, CK_BBOOL, SIGN_VERIFY_CONTEXT *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *); CK_RV sha1_hmac_verify(SESSION *, SIGN_VERIFY_CONTEXT *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG); CK_RV md5_hash(SESSION *, CK_BBOOL, DIGEST_CONTEXT *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *); CK_RV md5_hmac_sign(SESSION *, CK_BBOOL, SIGN_VERIFY_CONTEXT *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *); CK_RV md5_hmac_verify(SESSION *, SIGN_VERIFY_CONTEXT *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG); DL_NODE *dlist_add_as_first(DL_NODE *, void *); DL_NODE *dlist_add_as_last(DL_NODE *, void *); DL_NODE *dlist_find(DL_NODE *, void *); DL_NODE *dlist_get_first(DL_NODE *); DL_NODE *dlist_get_last(DL_NODE *); CK_ULONG dlist_length(DL_NODE *); DL_NODE *dlist_next(DL_NODE *); DL_NODE *dlist_prev(DL_NODE *); void dlist_purge(DL_NODE *); DL_NODE *dlist_remove_node(DL_NODE *, DL_NODE *); CK_RV attach_shm(void); CK_RV detach_shm(void); // encryption manager routines // CK_RV encr_mgr_init(SESSION *, ENCR_DECR_CONTEXT *, CK_ULONG, CK_MECHANISM *, CK_OBJECT_HANDLE); CK_RV encr_mgr_cleanup(ENCR_DECR_CONTEXT *); CK_RV encr_mgr_encrypt(SESSION *, CK_BBOOL, ENCR_DECR_CONTEXT *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *); CK_RV decr_mgr_init(SESSION *, ENCR_DECR_CONTEXT *, CK_ULONG, CK_MECHANISM *, CK_OBJECT_HANDLE); CK_RV decr_mgr_cleanup(ENCR_DECR_CONTEXT *); CK_RV decr_mgr_decrypt(SESSION *, CK_BBOOL, ENCR_DECR_CONTEXT *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *); CK_RV digest_mgr_cleanup(DIGEST_CONTEXT *); CK_RV digest_mgr_init(SESSION *, DIGEST_CONTEXT *, CK_MECHANISM *); CK_RV digest_mgr_digest(SESSION *, CK_BBOOL, DIGEST_CONTEXT *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *); CK_RV digest_mgr_digest_update(SESSION *, DIGEST_CONTEXT *, CK_BYTE *, CK_ULONG); CK_RV digest_mgr_digest_key(SESSION *, DIGEST_CONTEXT *, CK_OBJECT_HANDLE); CK_RV digest_mgr_digest_final(SESSION *, DIGEST_CONTEXT *, CK_BYTE *, CK_ULONG *); CK_RV key_mgr_generate_key_pair(SESSION *, CK_MECHANISM *, CK_ATTRIBUTE *, CK_ULONG, CK_ATTRIBUTE *, CK_ULONG, CK_OBJECT_HANDLE *, CK_OBJECT_HANDLE *); CK_RV key_mgr_wrap_key(SESSION *, CK_BBOOL, CK_MECHANISM *, CK_OBJECT_HANDLE, CK_OBJECT_HANDLE, CK_BYTE *, CK_ULONG *); CK_RV key_mgr_unwrap_key(SESSION *, CK_MECHANISM *, CK_ATTRIBUTE *, CK_ULONG, CK_BYTE *, CK_ULONG, CK_OBJECT_HANDLE, CK_OBJECT_HANDLE *); CK_RV sign_mgr_init(SESSION *, SIGN_VERIFY_CONTEXT *, CK_MECHANISM *, CK_BBOOL, CK_OBJECT_HANDLE); CK_RV sign_mgr_cleanup(SIGN_VERIFY_CONTEXT *); CK_RV sign_mgr_sign(SESSION *, CK_BBOOL, SIGN_VERIFY_CONTEXT *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *); CK_RV sign_mgr_sign_recover(SESSION *, CK_BBOOL, SIGN_VERIFY_CONTEXT *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *); CK_RV sign_mgr_sign_final(SESSION *, CK_BBOOL, SIGN_VERIFY_CONTEXT *, CK_BYTE *, CK_ULONG *); CK_RV sign_mgr_sign_update(SESSION *, SIGN_VERIFY_CONTEXT *, CK_BYTE *, CK_ULONG); CK_RV verify_mgr_init(SESSION *, SIGN_VERIFY_CONTEXT *, CK_MECHANISM *, CK_BBOOL, CK_OBJECT_HANDLE); CK_RV verify_mgr_cleanup(SIGN_VERIFY_CONTEXT *); CK_RV verify_mgr_verify(SESSION *, SIGN_VERIFY_CONTEXT *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG); CK_RV verify_mgr_verify_recover(SESSION *, CK_BBOOL, SIGN_VERIFY_CONTEXT *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *); CK_RV verify_mgr_verify_update(SESSION *, SIGN_VERIFY_CONTEXT *, CK_BYTE *, CK_ULONG); CK_RV verify_mgr_verify_final(SESSION *, SIGN_VERIFY_CONTEXT *, CK_BYTE *, CK_ULONG); // session manager routines // CK_RV session_mgr_close_all_sessions(void); CK_RV session_mgr_close_session(SESSION *); SESSION *session_mgr_find(CK_SESSION_HANDLE); CK_RV session_mgr_login_all(CK_USER_TYPE); CK_RV session_mgr_logout_all(void); CK_RV session_mgr_new(CK_ULONG, SESSION **); CK_BBOOL session_mgr_readonly_exists(void); CK_BBOOL session_mgr_so_session_exists(void); CK_BBOOL session_mgr_user_session_exists(void); CK_BBOOL session_mgr_public_session_exists(void); CK_RV session_mgr_get_op_state(SESSION *, CK_BBOOL, CK_BYTE *, CK_ULONG *); CK_RV session_mgr_set_op_state(SESSION *, CK_OBJECT_HANDLE, CK_OBJECT_HANDLE, CK_BYTE *); CK_RV object_mgr_add(SESSION *, CK_ATTRIBUTE *, CK_ULONG, CK_OBJECT_HANDLE *); CK_RV object_mgr_add_to_map(SESSION *, OBJECT *, CK_OBJECT_HANDLE *); CK_RV object_mgr_add_to_shm(OBJECT *); CK_RV object_mgr_del_from_shm(OBJECT *); CK_RV object_mgr_copy(SESSION *, CK_ATTRIBUTE *, CK_ULONG, CK_OBJECT_HANDLE, CK_OBJECT_HANDLE *); CK_RV object_mgr_create_final(SESSION *, OBJECT *, CK_OBJECT_HANDLE *); CK_RV object_mgr_create_skel(SESSION *, CK_ATTRIBUTE *, CK_ULONG, CK_ULONG, CK_ULONG, CK_ULONG, OBJECT **); CK_RV object_mgr_destroy_object(SESSION *, CK_OBJECT_HANDLE); CK_RV object_mgr_destroy_token_objects(TSS_HCONTEXT); CK_RV object_mgr_find_in_map1(TSS_HCONTEXT, CK_OBJECT_HANDLE, OBJECT **); CK_RV object_mgr_find_in_map2(TSS_HCONTEXT, OBJECT *, CK_OBJECT_HANDLE *); CK_RV object_mgr_find_init(SESSION *, CK_ATTRIBUTE *, CK_ULONG); CK_RV object_mgr_find_build_list(SESSION *, CK_ATTRIBUTE *, CK_ULONG, DL_NODE *, CK_BBOOL public_only); CK_RV object_mgr_find_final(SESSION *); CK_RV object_mgr_get_attribute_values(SESSION *, CK_OBJECT_HANDLE, CK_ATTRIBUTE *, CK_ULONG); CK_RV object_mgr_get_object_size(TSS_HCONTEXT, CK_OBJECT_HANDLE, CK_ULONG *); CK_BBOOL object_mgr_invalidate_handle1(CK_OBJECT_HANDLE handle); CK_BBOOL object_mgr_invalidate_handle2(OBJECT *); CK_BBOOL object_mgr_purge_session_objects(SESSION *, SESS_OBJ_TYPE); CK_BBOOL object_mgr_purge_token_objects(TSS_HCONTEXT); CK_BBOOL object_mgr_purge_private_token_objects(TSS_HCONTEXT); CK_RV object_mgr_remove_from_map(CK_OBJECT_HANDLE); CK_RV object_mgr_restore_obj(CK_BYTE *, OBJECT *); CK_RV object_mgr_set_attribute_values(SESSION *, CK_OBJECT_HANDLE, CK_ATTRIBUTE *, CK_ULONG); CK_BBOOL object_mgr_purge_map(SESSION *, SESS_OBJ_TYPE); CK_RV object_create(CK_ATTRIBUTE *, CK_ULONG, OBJECT **); CK_RV object_create_skel(CK_ATTRIBUTE *, CK_ULONG, CK_ULONG, CK_ULONG, CK_ULONG, OBJECT **); CK_RV object_copy(CK_ATTRIBUTE *, CK_ULONG, OBJECT *, OBJECT **); CK_RV object_flatten(OBJECT *, CK_BYTE **, CK_ULONG_32 *); CK_BBOOL object_free(OBJECT *); CK_RV object_get_attribute_values(OBJECT *, CK_ATTRIBUTE *, CK_ULONG); CK_ULONG object_get_size(OBJECT *); CK_RV object_restore(CK_BYTE *, OBJECT **, CK_BBOOL replace); CK_RV object_set_attribute_values(OBJECT *, CK_ATTRIBUTE *, CK_ULONG); CK_BBOOL object_is_modifiable(OBJECT *); CK_BBOOL object_is_private(OBJECT *); CK_BBOOL object_is_public(OBJECT *); CK_BBOOL object_is_token_object(OBJECT *); CK_BBOOL object_is_session_object(OBJECT *); CK_BBOOL is_attribute_defined(CK_ATTRIBUTE_TYPE); CK_RV template_add_attributes(TEMPLATE *, CK_ATTRIBUTE *, CK_ULONG); CK_RV template_add_default_attributes(TEMPLATE *, CK_ULONG, CK_ULONG, CK_ULONG); CK_BBOOL template_attribute_find(TEMPLATE *, CK_ATTRIBUTE_TYPE, CK_ATTRIBUTE **); void template_attribute_find_multiple(TEMPLATE *, ATTRIBUTE_PARSE_LIST *, CK_ULONG); CK_BBOOL template_check_exportability(TEMPLATE *, CK_ATTRIBUTE_TYPE type); CK_RV template_check_required_attributes(TEMPLATE *, CK_ULONG, CK_ULONG, CK_ULONG); CK_RV template_check_required_base_attributes(TEMPLATE *, CK_ULONG); CK_BBOOL template_compare(CK_ATTRIBUTE *, CK_ULONG, TEMPLATE *); CK_RV template_copy(TEMPLATE *, TEMPLATE *); CK_RV template_flatten(TEMPLATE *, CK_BYTE *); CK_RV template_free(TEMPLATE *); CK_BBOOL template_get_class(TEMPLATE *, CK_ULONG *, CK_ULONG *); CK_ULONG template_get_count(TEMPLATE *); CK_ULONG template_get_size(TEMPLATE *); CK_ULONG template_get_compressed_size(TEMPLATE *); CK_RV template_set_default_common_attributes(TEMPLATE *); CK_RV template_merge(TEMPLATE *, TEMPLATE **); CK_RV template_update_attribute(TEMPLATE *, CK_ATTRIBUTE *); CK_RV template_unflatten(TEMPLATE **, CK_BYTE *, CK_ULONG); CK_RV template_validate_attribute(TEMPLATE *, CK_ATTRIBUTE *, CK_ULONG, CK_ULONG, CK_ULONG); CK_RV template_validate_attributes(TEMPLATE *, CK_ULONG, CK_ULONG, CK_ULONG); CK_RV template_validate_base_attribute(TEMPLATE *, CK_ATTRIBUTE *, CK_ULONG); // DATA OBJECT ROUTINES // CK_RV data_object_check_required_attributes(TEMPLATE *, CK_ULONG); CK_RV data_object_set_default_attributes(TEMPLATE *, CK_ULONG); CK_RV data_object_validate_attribute(TEMPLATE *, CK_ATTRIBUTE *, CK_ULONG); // CERTIFICATE ROUTINES CK_RV cert_validate_attribute(TEMPLATE *, CK_ATTRIBUTE *, CK_ULONG); CK_RV cert_x509_check_required_attributes(TEMPLATE *, CK_ULONG); CK_RV cert_x509_set_default_attributes(TEMPLATE *, CK_ULONG); CK_RV cert_x509_validate_attribute(TEMPLATE *, CK_ATTRIBUTE *, CK_ULONG); CK_RV cert_vendor_check_required_attributes(TEMPLATE *, CK_ULONG); CK_RV cert_vendor_validate_attribute(TEMPLATE *, CK_ATTRIBUTE *, CK_ULONG); // // KEY ROUTINES // CK_RV key_object_check_required_attributes(TEMPLATE *, CK_ULONG); CK_RV key_object_set_default_attributes(TEMPLATE *, CK_ULONG); CK_RV key_object_validate_attribute(TEMPLATE *, CK_ATTRIBUTE *, CK_ULONG); CK_RV publ_key_check_required_attributes(TEMPLATE *, CK_ULONG); CK_RV publ_key_set_default_attributes(TEMPLATE *, CK_ULONG); CK_RV publ_key_validate_attribute(TEMPLATE *, CK_ATTRIBUTE *, CK_ULONG); CK_RV priv_key_check_required_attributes(TEMPLATE *, CK_ULONG); CK_RV priv_key_set_default_attributes(TEMPLATE *, CK_ULONG); CK_RV priv_key_unwrap(TEMPLATE *, CK_ULONG, CK_BYTE *, CK_ULONG); CK_RV priv_key_validate_attribute(TEMPLATE *, CK_ATTRIBUTE *, CK_ULONG); CK_BBOOL secret_key_check_exportability(CK_ATTRIBUTE_TYPE type); CK_RV secret_key_check_required_attributes(TEMPLATE *, CK_ULONG); CK_RV secret_key_set_default_attributes(TEMPLATE *, CK_ULONG); CK_RV secret_key_unwrap(TEMPLATE *, CK_ULONG, CK_BYTE *, CK_ULONG, CK_BBOOL fromend); CK_RV secret_key_validate_attribute(TEMPLATE *, CK_ATTRIBUTE *, CK_ULONG); // rsa routines // CK_RV rsa_publ_check_required_attributes(TEMPLATE *, CK_ULONG); CK_RV rsa_publ_validate_attribute(TEMPLATE *, CK_ATTRIBUTE *, CK_ULONG); CK_RV rsa_publ_set_default_attributes(TEMPLATE *, CK_ULONG); CK_BBOOL rsa_priv_check_exportability(CK_ATTRIBUTE_TYPE type); CK_RV rsa_priv_check_required_attributes(TEMPLATE *, CK_ULONG); CK_RV rsa_priv_set_default_attributes(TEMPLATE *, CK_ULONG); CK_RV rsa_priv_validate_attribute(TEMPLATE *, CK_ATTRIBUTE *, CK_ULONG); CK_RV rsa_priv_wrap_get_data(TEMPLATE *, CK_BBOOL, CK_BYTE **, CK_ULONG *); CK_RV rsa_priv_unwrap(TEMPLATE *, CK_BYTE *, CK_ULONG); // Generic secret key routines CK_RV generic_secret_check_required_attributes(TEMPLATE *, CK_ULONG); CK_RV generic_secret_set_default_attributes(TEMPLATE *, CK_ULONG); CK_RV generic_secret_validate_attribute(TEMPLATE *, CK_ATTRIBUTE *, CK_ULONG); CK_RV generic_secret_wrap_get_data(TEMPLATE *, CK_BBOOL, CK_BYTE **, CK_ULONG *); CK_RV generic_secret_unwrap(TEMPLATE *, CK_BYTE *, CK_ULONG, CK_BBOOL fromend); CK_RV tpm_encrypt_data(TSS_HCONTEXT, TSS_HKEY, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *); CK_RV tpm_decrypt_data(TSS_HCONTEXT, TSS_HKEY, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *); CK_ULONG ber_encode_INTEGER(CK_BBOOL, CK_BYTE **, CK_ULONG *, CK_BYTE *, CK_ULONG); CK_RV ber_decode_INTEGER(CK_BYTE *, CK_BYTE **, CK_ULONG *, CK_ULONG *); CK_RV ber_encode_OCTET_STRING(CK_BBOOL, CK_BYTE **, CK_ULONG *, CK_BYTE *, CK_ULONG); CK_RV ber_decode_OCTET_STRING(CK_BYTE *, CK_BYTE **, CK_ULONG *, CK_ULONG *); CK_RV ber_encode_SEQUENCE(CK_BBOOL, CK_BYTE **, CK_ULONG *, CK_BYTE *, CK_ULONG); CK_RV ber_decode_SEQUENCE(CK_BYTE *, CK_BYTE **, CK_ULONG *, CK_ULONG *); CK_RV ber_encode_PrivateKeyInfo(CK_BBOOL, CK_BYTE **, CK_ULONG *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG); CK_RV ber_decode_PrivateKeyInfo(CK_BYTE *, CK_ULONG, CK_BYTE **, CK_ULONG *, CK_BYTE **); CK_RV ber_encode_RSAPrivateKey(CK_BBOOL, CK_BYTE **, CK_ULONG *, CK_ATTRIBUTE *, CK_ATTRIBUTE *, CK_ATTRIBUTE *, CK_ATTRIBUTE *, CK_ATTRIBUTE *, CK_ATTRIBUTE *, CK_ATTRIBUTE *, CK_ATTRIBUTE *); CK_RV ber_decode_RSAPrivateKey(CK_BYTE *, CK_ULONG, CK_ATTRIBUTE **, CK_ATTRIBUTE **, CK_ATTRIBUTE **, CK_ATTRIBUTE **, CK_ATTRIBUTE **, CK_ATTRIBUTE **, CK_ATTRIBUTE **, CK_ATTRIBUTE **); CK_RV ber_encode_DSAPrivateKey(CK_BBOOL, CK_BYTE **, CK_ULONG *, CK_ATTRIBUTE *, CK_ATTRIBUTE *, CK_ATTRIBUTE *, CK_ATTRIBUTE *); CK_RV ber_decode_DSAPrivateKey(CK_BYTE *, CK_ULONG, CK_ATTRIBUTE **, CK_ATTRIBUTE **, CK_ATTRIBUTE **, CK_ATTRIBUTE **); #define APPID "TPM_STDLL" /* log to stdout */ #define LogMessage(dest, priority, layer, fmt, ...) \ (void) fprintf(dest, "%s %s %s:%d " fmt "\n", (char *)priority, \ (char *)layer, (char *)__FILE__,\ (int)__LINE__, __VA_ARGS__); #define LogMessage1(dest, priority, layer, data) \ (void) fprintf(dest, "%s %s %s:%d %s\n", priority, layer, __FILE__, \ __LINE__, data); /* Debug logging */ #ifdef DEBUG #define LogDebug(fmt, ...) LogMessage(stdout, "LOG_DEBUG", APPID, \ fmt, __VA_ARGS__) #define LogDebug1(data) LogMessage1(stdout, "LOG_DEBUG", APPID, data) /* Error logging */ #define LogError(fmt, ...) LogMessage(stderr, "LOG_ERR", APPID,\ "ERROR: " fmt, __VA_ARGS__) #define LogError1(data) LogMessage1(stderr, "LOG_ERR", APPID,\ "ERROR: " data) /* Warn logging */ #define LogWarn(fmt, ...) LogMessage(stdout, "LOG_WARNING", APPID,\ "WARNING: " fmt, __VA_ARGS__) #define LogWarn1(data) LogMessage1(stdout, "LOG_WARNING", APPID,\ "WARNING: " data) /* Info Logging */ #define LogInfo(fmt, ...) LogMessage(stdout, "LOG_INFO", APPID,\ fmt, __VA_ARGS__) #define LogInfo1(data) LogMessage1(stdout, "LOG_INFO", APPID, data) #define st_err_log(...) LogMessage(stderr, "ST MSG", APPID,\ "", __VA_ARGS__) #else #define LogDebug(...) #define LogDebug1(...) #define LogBlob(...) #define LogError(...) #define LogError1(...) #define LogWarn(...) #define LogWarn1(...) #define LogInfo(...) #define LogInfo1(...) #define st_err_log(...) #endif /* * CK_FUNCTION_LIST is a structure holding a Cryptoki spec * version and pointers of appropriate types to all the * Cryptoki functions */ /* CK_FUNCTION_LIST is new for v2.0 */ typedef CK_RV (CK_PTR ST_C_Initialize) (void *ppFunctionList, CK_SLOT_ID slotID, CK_CHAR_PTR pCorrelator); typedef CK_RV (CK_PTR ST_C_Finalize) (CK_VOID_PTR pReserved); typedef CK_RV (CK_PTR ST_C_Terminate)(); typedef CK_RV (CK_PTR ST_C_GetInfo) (CK_INFO_PTR pInfo); typedef CK_RV (CK_PTR ST_C_GetFunctionList) (CK_FUNCTION_LIST_PTR_PTR ppFunctionList); typedef CK_RV (CK_PTR ST_C_GetSlotList) (CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pusCount); typedef CK_RV (CK_PTR ST_C_GetSlotInfo) (CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo); typedef CK_RV (CK_PTR ST_C_GetTokenInfo) (CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo); typedef CK_RV (CK_PTR ST_C_GetMechanismList) (CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pusCount); typedef CK_RV (CK_PTR ST_C_GetMechanismInfo) (CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo); typedef CK_RV (CK_PTR ST_C_InitToken) (CK_SLOT_ID slotID, CK_CHAR_PTR pPin, CK_ULONG usPinLen, CK_CHAR_PTR pLabel); typedef CK_RV (CK_PTR ST_C_InitPIN) (ST_SESSION_T hSession, CK_CHAR_PTR pPin, CK_ULONG usPinLen); typedef CK_RV (CK_PTR ST_C_SetPIN) (ST_SESSION_T hSession, CK_CHAR_PTR pOldPin, CK_ULONG usOldLen, CK_CHAR_PTR pNewPin, CK_ULONG usNewLen); typedef CK_RV (CK_PTR ST_C_OpenSession) (CK_SLOT_ID slotID, CK_FLAGS flags, CK_SESSION_HANDLE_PTR phSession); typedef CK_RV (CK_PTR ST_C_CloseSession) (ST_SESSION_T hSession); typedef CK_RV (CK_PTR ST_C_CloseAllSessions) (CK_SLOT_ID slotID); typedef CK_RV (CK_PTR ST_C_GetSessionInfo) (ST_SESSION_T hSession, CK_SESSION_INFO_PTR pInfo); typedef CK_RV (CK_PTR ST_C_GetOperationState) (ST_SESSION_T hSession, CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen); typedef CK_RV (CK_PTR ST_C_SetOperationState) (ST_SESSION_T hSession, CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen, CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey); typedef CK_RV (CK_PTR ST_C_Login)(ST_SESSION_T hSession, CK_USER_TYPE userType, CK_CHAR_PTR pPin, CK_ULONG usPinLen); typedef CK_RV (CK_PTR ST_C_Logout)(ST_SESSION_T hSession); typedef CK_RV (CK_PTR ST_C_CreateObject) (ST_SESSION_T hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usCount, CK_OBJECT_HANDLE_PTR phObject); typedef CK_RV (CK_PTR ST_C_CopyObject) (ST_SESSION_T hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usCount, CK_OBJECT_HANDLE_PTR phNewObject); typedef CK_RV (CK_PTR ST_C_DestroyObject) (ST_SESSION_T hSession, CK_OBJECT_HANDLE hObject); typedef CK_RV (CK_PTR ST_C_GetObjectSize) (ST_SESSION_T hSession, CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pusSize); typedef CK_RV (CK_PTR ST_C_GetAttributeValue) (ST_SESSION_T hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usCount); typedef CK_RV (CK_PTR ST_C_SetAttributeValue) (ST_SESSION_T hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usCount); typedef CK_RV (CK_PTR ST_C_FindObjectsInit) (ST_SESSION_T hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usCount); typedef CK_RV (CK_PTR ST_C_FindObjects) (ST_SESSION_T hSession, CK_OBJECT_HANDLE_PTR phObject, CK_ULONG usMaxObjectCount, CK_ULONG_PTR pusObjectCount); typedef CK_RV (CK_PTR ST_C_FindObjectsFinal) (ST_SESSION_T hSession); typedef CK_RV (CK_PTR ST_C_EncryptInit) (ST_SESSION_T hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey); typedef CK_RV (CK_PTR ST_C_Encrypt) (ST_SESSION_T hSession, CK_BYTE_PTR pData, CK_ULONG usDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pusEncryptedDataLen); typedef CK_RV (CK_PTR ST_C_EncryptUpdate) (ST_SESSION_T hSession, CK_BYTE_PTR pPart, CK_ULONG usPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pusEncryptedPartLen); typedef CK_RV (CK_PTR ST_C_EncryptFinal) (ST_SESSION_T hSession, CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pusLastEncryptedPartLen); typedef CK_RV (CK_PTR ST_C_DecryptInit) (ST_SESSION_T hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey); typedef CK_RV (CK_PTR ST_C_Decrypt) (ST_SESSION_T hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG usEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pusDataLen); typedef CK_RV (CK_PTR ST_C_DecryptUpdate) (ST_SESSION_T hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG usEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pusPartLen); typedef CK_RV (CK_PTR ST_C_DecryptFinal) (ST_SESSION_T hSession, CK_BYTE_PTR pLastPart, CK_ULONG_PTR pusLastPartLen); typedef CK_RV (CK_PTR ST_C_DigestInit) (ST_SESSION_T hSession, CK_MECHANISM_PTR pMechanism); typedef CK_RV (CK_PTR ST_C_Digest) (ST_SESSION_T hSession, CK_BYTE_PTR pData, CK_ULONG usDataLen, CK_BYTE_PTR pDigest, CK_ULONG_PTR pusDigestLen); typedef CK_RV (CK_PTR ST_C_DigestUpdate) (ST_SESSION_T hSession, CK_BYTE_PTR pPart, CK_ULONG usPartLen); typedef CK_RV (CK_PTR ST_C_DigestKey) (ST_SESSION_T hSession, CK_OBJECT_HANDLE hKey); typedef CK_RV (CK_PTR ST_C_DigestFinal) (ST_SESSION_T hSession, CK_BYTE_PTR pDigest, CK_ULONG_PTR pusDigestLen); typedef CK_RV (CK_PTR ST_C_SignInit) (ST_SESSION_T hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey); typedef CK_RV (CK_PTR ST_C_Sign) (ST_SESSION_T hSession, CK_BYTE_PTR pData, CK_ULONG usDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pusSignatureLen); typedef CK_RV (CK_PTR ST_C_SignUpdate) (ST_SESSION_T hSession, CK_BYTE_PTR pPart, CK_ULONG usPartLen); typedef CK_RV (CK_PTR ST_C_SignFinal) (ST_SESSION_T hSession, CK_BYTE_PTR pSignature, CK_ULONG_PTR pusSignatureLen); typedef CK_RV (CK_PTR ST_C_SignRecoverInit) (ST_SESSION_T hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey); typedef CK_RV (CK_PTR ST_C_SignRecover) (ST_SESSION_T hSession, CK_BYTE_PTR pData, CK_ULONG usDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pusSignatureLen); typedef CK_RV (CK_PTR ST_C_VerifyInit) (ST_SESSION_T hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey); typedef CK_RV (CK_PTR ST_C_Verify) (ST_SESSION_T hSession, CK_BYTE_PTR pData, CK_ULONG usDataLen, CK_BYTE_PTR pSignature, CK_ULONG usSignatureLen); typedef CK_RV (CK_PTR ST_C_VerifyUpdate) (ST_SESSION_T hSession, CK_BYTE_PTR pPart, CK_ULONG usPartLen); typedef CK_RV (CK_PTR ST_C_VerifyFinal) (ST_SESSION_T hSession, CK_BYTE_PTR pSignature, CK_ULONG usSignatureLen); typedef CK_RV (CK_PTR ST_C_VerifyRecoverInit) (ST_SESSION_T hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey); typedef CK_RV (CK_PTR ST_C_VerifyRecover) (ST_SESSION_T hSession, CK_BYTE_PTR pSignature, CK_ULONG usSignatureLen, CK_BYTE_PTR pData, CK_ULONG_PTR pusDataLen); typedef CK_RV (CK_PTR ST_C_DigestEncryptUpdate) (ST_SESSION_T hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen); typedef CK_RV (CK_PTR ST_C_DecryptDigestUpdate) (ST_SESSION_T hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen); typedef CK_RV (CK_PTR ST_C_SignEncryptUpdate) (ST_SESSION_T hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen); typedef CK_RV (CK_PTR ST_C_DecryptVerifyUpdate) (ST_SESSION_T hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen); typedef CK_RV (CK_PTR ST_C_GenerateKey) (ST_SESSION_T hSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usCount, CK_OBJECT_HANDLE_PTR phKey); typedef CK_RV (CK_PTR ST_C_GenerateKeyPair) (ST_SESSION_T hSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG usPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG usPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPrivateKey, CK_OBJECT_HANDLE_PTR phPublicKey); typedef CK_RV (CK_PTR ST_C_WrapKey) (ST_SESSION_T hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey, CK_ULONG_PTR pusWrappedKeyLen); typedef CK_RV (CK_PTR ST_C_UnwrapKey) (ST_SESSION_T hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey, CK_BYTE_PTR pWrappedKey, CK_ULONG usWrappedKeyLen, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usAttributeCount, CK_OBJECT_HANDLE_PTR phKey); typedef CK_RV (CK_PTR ST_C_DeriveKey) (ST_SESSION_T hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usAttributeCount, CK_OBJECT_HANDLE_PTR phKey); typedef CK_RV (CK_PTR ST_C_SeedRandom) (ST_SESSION_T hSession, CK_BYTE_PTR pSeed, CK_ULONG usSeedLen); typedef CK_RV (CK_PTR ST_C_GenerateRandom) (ST_SESSION_T hSession, CK_BYTE_PTR pRandomData, CK_ULONG usRandomLen); typedef CK_RV (CK_PTR ST_C_GetFunctionStatus) (ST_SESSION_T hSession); typedef CK_RV (CK_PTR ST_C_CancelFunction) (ST_SESSION_T hSession); typedef CK_RV (CK_PTR ST_Notify) (ST_SESSION_T hSession, CK_NOTIFICATION event, CK_VOID_PTR pApplication); typedef CK_RV (CK_PTR ST_C_WaitForSlotEvent) (CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, CK_VOID_PTR pReserved); struct ST_FCN_LIST { ST_C_Initialize ST_Initialize; ST_C_Finalize ST_Finalize; ST_C_GetTokenInfo ST_GetTokenInfo; ST_C_GetMechanismList ST_GetMechanismList; ST_C_GetMechanismInfo ST_GetMechanismInfo; ST_C_InitToken ST_InitToken; ST_C_InitPIN ST_InitPIN; ST_C_SetPIN ST_SetPIN; ST_C_OpenSession ST_OpenSession; ST_C_CloseSession ST_CloseSession; ST_C_GetSessionInfo ST_GetSessionInfo; ST_C_GetOperationState ST_GetOperationState; ST_C_SetOperationState ST_SetOperationState; ST_C_Login ST_Login; ST_C_Logout ST_Logout; ST_C_CreateObject ST_CreateObject; ST_C_CopyObject ST_CopyObject; ST_C_DestroyObject ST_DestroyObject; ST_C_GetObjectSize ST_GetObjectSize; ST_C_GetAttributeValue ST_GetAttributeValue; ST_C_SetAttributeValue ST_SetAttributeValue; ST_C_FindObjectsInit ST_FindObjectsInit; ST_C_FindObjects ST_FindObjects; ST_C_FindObjectsFinal ST_FindObjectsFinal; ST_C_EncryptInit ST_EncryptInit; ST_C_Encrypt ST_Encrypt; ST_C_EncryptUpdate ST_EncryptUpdate; ST_C_EncryptFinal ST_EncryptFinal; ST_C_DecryptInit ST_DecryptInit; ST_C_Decrypt ST_Decrypt; ST_C_DecryptUpdate ST_DecryptUpdate; ST_C_DecryptFinal ST_DecryptFinal; ST_C_DigestInit ST_DigestInit; ST_C_Digest ST_Digest; ST_C_DigestUpdate ST_DigestUpdate; ST_C_DigestKey ST_DigestKey; ST_C_DigestFinal ST_DigestFinal; ST_C_SignInit ST_SignInit; ST_C_Sign ST_Sign; ST_C_SignUpdate ST_SignUpdate; ST_C_SignFinal ST_SignFinal; ST_C_SignRecoverInit ST_SignRecoverInit; ST_C_SignRecover ST_SignRecover; ST_C_VerifyInit ST_VerifyInit; ST_C_Verify ST_Verify; ST_C_VerifyUpdate ST_VerifyUpdate; ST_C_VerifyFinal ST_VerifyFinal; ST_C_VerifyRecoverInit ST_VerifyRecoverInit; ST_C_VerifyRecover ST_VerifyRecover; ST_C_DigestEncryptUpdate ST_DigestEncryptUpdate; ST_C_DecryptDigestUpdate ST_DecryptDigestUpdate; ST_C_SignEncryptUpdate ST_SignEncryptUpdate; ST_C_DecryptVerifyUpdate ST_DecryptVerifyUpdate; ST_C_GenerateKey ST_GenerateKey; ST_C_GenerateKeyPair ST_GenerateKeyPair; ST_C_WrapKey ST_WrapKey; ST_C_UnwrapKey ST_UnwrapKey; ST_C_DeriveKey ST_DeriveKey; ST_C_SeedRandom ST_SeedRandom; ST_C_GenerateRandom ST_GenerateRandom; ST_C_GetFunctionStatus ST_GetFunctionStatus; ST_C_CancelFunction ST_CancelFunction; }; typedef struct ST_FCN_LIST STDLL_FcnList_t; #endif /* _TPMTOK_INT_H */ /* * The Initial Developer of the Original Code is International * Business Machines Corporation. Portions created by IBM * Corporation are Copyright (C) 2005 International Business * Machines Corporation. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the Common Public License as published by * IBM Corporation; either version 1 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * Common Public License for more details. * * You should have received a copy of the Common Public License * along with this program; if not, a copy can be viewed at * http://www.opensource.org/licenses/cpl1.0.php. */ /* (C) COPYRIGHT International Business Machines Corp. 2001, 2002, 2005 */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include "tpmtok_int.h" static CK_SLOT_INFO slot_info; // Function: dlist_add_as_first() // // Adds the specified node to the start of the list // // Returns: pointer to the start of the list // DL_NODE * dlist_add_as_first(DL_NODE *list, void *data) { DL_NODE *node = NULL; if (! data) return (list); node = (DL_NODE *)malloc(sizeof (DL_NODE)); if (! node) return (NULL); node->data = data; node->prev = NULL; node->next = list; if (list) list->prev = node; return (node); } // Function: dlist_add_as_last() // // Adds the specified node to the end of the list // // Returns: pointer to the start of the list // DL_NODE * dlist_add_as_last(DL_NODE *list, void *data) { DL_NODE *node = NULL; if (! data) return (list); node = (DL_NODE *)malloc(sizeof (DL_NODE)); if (! node) return (NULL); node->data = data; node->next = NULL; if (! list) { node->prev = NULL; return (node); } else { DL_NODE *temp = dlist_get_last(list); temp->next = node; node->prev = temp; return (list); } } // Function: dlist_find() // DL_NODE * dlist_find(DL_NODE *list, void *data) { DL_NODE *node = list; while (node && node->data != data) node = node->next; return (node); } // Function: dlist_get_first() // // Returns the last node in the list or NULL if list is empty // DL_NODE * dlist_get_first(DL_NODE *list) { DL_NODE *temp = list; if (! list) return (NULL); while (temp->prev != NULL) temp = temp->prev; return (temp); } // Function: dlist_get_last() // // Returns the last node in the list or NULL if list is empty // DL_NODE * dlist_get_last(DL_NODE *list) { DL_NODE *temp = list; if (! list) return (NULL); while (temp->next != NULL) temp = temp->next; return (temp); } // // CK_ULONG dlist_length(DL_NODE *list) { DL_NODE *temp = list; CK_ULONG len = 0; while (temp) { len++; temp = temp->next; } return (len); } // // DL_NODE * dlist_next(DL_NODE *node) { if (! node) return (NULL); return (node->next); } // // DL_NODE * dlist_prev(DL_NODE *node) { if (! node) return (NULL); return (node->prev); } // // void dlist_purge(DL_NODE *list) { DL_NODE *node; if (! list) return; do { node = list->next; free(list); list = node; } while (list); } // Function: dlist_remove_node() // // Attempts to remove the specified node from the list. The caller is // responsible for freeing the data associated with the node prior to // calling this routine // DL_NODE * dlist_remove_node(DL_NODE *list, DL_NODE *node) { DL_NODE *temp = list; if (! list || ! node) return (NULL); // special case: removing head of the list // if (list == node) { temp = list->next; if (temp) temp->prev = NULL; free(list); return (temp); } // we have no guarantee that the node is in the list // so search through the list to find it // while ((temp != NULL) && (temp->next != node)) temp = temp->next; if (temp != NULL) { DL_NODE *next = node->next; temp->next = next; if (next) next->prev = temp; free(node); } return (list); } extern void set_perm(int); void CreateXProcLock(void *xproc) { pthread_mutexattr_t mtxattr; (void) pthread_mutexattr_init(&mtxattr); (void) pthread_mutexattr_setpshared(&mtxattr, PTHREAD_PROCESS_SHARED); (void) pthread_mutex_init((pthread_mutex_t *)xproc, &mtxattr); } int DestroyXProcLock(void *xproc) { return (pthread_mutex_destroy((pthread_mutex_t *)xproc)); } int XProcLock(void *xproc) { return (pthread_mutex_lock((pthread_mutex_t *)xproc)); } int XProcUnLock(void *xproc) { return (pthread_mutex_unlock((pthread_mutex_t *)xproc)); } // // // is_attribute_defined() // // determine whether the specified attribute is defined by Cryptoki // CK_BBOOL is_attribute_defined(CK_ATTRIBUTE_TYPE type) { if (type >= CKA_VENDOR_DEFINED) return (TRUE); switch (type) { case CKA_CLASS: case CKA_TOKEN: case CKA_PRIVATE: case CKA_LABEL: case CKA_APPLICATION: case CKA_VALUE: case CKA_CERTIFICATE_TYPE: case CKA_ISSUER: case CKA_SERIAL_NUMBER: case CKA_KEY_TYPE: case CKA_SUBJECT: case CKA_ID: case CKA_SENSITIVE: case CKA_ENCRYPT: case CKA_DECRYPT: case CKA_WRAP: case CKA_UNWRAP: case CKA_SIGN: case CKA_SIGN_RECOVER: case CKA_VERIFY: case CKA_VERIFY_RECOVER: case CKA_DERIVE: case CKA_START_DATE: case CKA_END_DATE: case CKA_MODULUS: case CKA_MODULUS_BITS: case CKA_PUBLIC_EXPONENT: case CKA_PRIVATE_EXPONENT: case CKA_PRIME_1: case CKA_PRIME_2: case CKA_EXPONENT_1: case CKA_EXPONENT_2: case CKA_COEFFICIENT: case CKA_PRIME: case CKA_SUBPRIME: case CKA_BASE: case CKA_VALUE_BITS: case CKA_VALUE_LEN: case CKA_EXTRACTABLE: case CKA_LOCAL: case CKA_NEVER_EXTRACTABLE: case CKA_ALWAYS_SENSITIVE: case CKA_MODIFIABLE: case CKA_ECDSA_PARAMS: case CKA_EC_POINT: case CKA_HW_FEATURE_TYPE: case CKA_HAS_RESET: case CKA_RESET_ON_INIT: case CKA_KEY_GEN_MECHANISM: case CKA_PRIME_BITS: case CKA_SUBPRIME_BITS: case CKA_OBJECT_ID: case CKA_AC_ISSUER: case CKA_OWNER: case CKA_ATTR_TYPES: case CKA_TRUSTED: return (TRUE); } return (FALSE); } void init_slot_info(TOKEN_DATA *td) { /* * Much of the token info is pulled from the TPM itself when * C_Initialize is called. */ (void) (void) memset(&slot_info.slotDescription, ' ', sizeof (slot_info.slotDescription) - 1); (void) (void) memset(&slot_info.manufacturerID, ' ', sizeof (slot_info.manufacturerID) - 1); (void) (void) memcpy(&slot_info.slotDescription, "PKCS#11 Interface for TPM", strlen("PKCS#11 Interface for TPM")); (void) (void) memcpy(&slot_info.manufacturerID, td->token_info.manufacturerID, strlen((char *)td->token_info.manufacturerID)); slot_info.hardwareVersion = nv_token_data->token_info.hardwareVersion; slot_info.firmwareVersion = nv_token_data->token_info.firmwareVersion; slot_info.flags = CKF_TOKEN_PRESENT | CKF_HW_SLOT; } /*ARGSUSED*/ void copy_slot_info(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR sinfo) { if (sinfo != NULL) (void) memcpy(sinfo, &slot_info, sizeof (slot_info)); } static void init_token_info(TOKEN_DATA *td) { CK_TOKEN_INFO *token_info = NULL; token_info = &td->token_info; (void) memset(token_info->model, ' ', sizeof (token_info->model)); (void) memset(token_info->serialNumber, ' ', sizeof (token_info->serialNumber)); // // I don't see any API support for changing the clock so // we will use the system clock for the token's clock. // token_info->flags = CKF_RNG | CKF_LOGIN_REQUIRED | CKF_CLOCK_ON_TOKEN | CKF_SO_PIN_TO_BE_CHANGED; if (memcmp(td->user_pin_sha, "00000000000000000000", SHA1_DIGEST_LENGTH) != 0) token_info->flags |= CKF_USER_PIN_INITIALIZED; else token_info->flags |= CKF_USER_PIN_TO_BE_CHANGED; // For the release, we made these // values as CK_UNAVAILABLE_INFORMATION // token_info->ulMaxSessionCount = (CK_ULONG)CK_UNAVAILABLE_INFORMATION; token_info->ulSessionCount = (CK_ULONG)CK_UNAVAILABLE_INFORMATION; token_info->ulMaxRwSessionCount = (CK_ULONG)CK_UNAVAILABLE_INFORMATION; token_info->ulRwSessionCount = (CK_ULONG)CK_UNAVAILABLE_INFORMATION; token_info->ulMaxPinLen = MAX_PIN_LEN; token_info->ulMinPinLen = MIN_PIN_LEN; token_info->ulTotalPublicMemory = (CK_ULONG)CK_UNAVAILABLE_INFORMATION; token_info->ulFreePublicMemory = (CK_ULONG)CK_UNAVAILABLE_INFORMATION; token_info->ulTotalPrivateMemory = (CK_ULONG)CK_UNAVAILABLE_INFORMATION; token_info->ulFreePrivateMemory = (CK_ULONG)CK_UNAVAILABLE_INFORMATION; (void) memset(token_info->utcTime, ' ', sizeof (token_info->utcTime)); } CK_RV init_token_data(TSS_HCONTEXT hContext, TOKEN_DATA *td) { CK_RV rc; (void) memset((char *)td, 0, sizeof (nv_token_data)); // // the normal USER pin is not set when the token is initialized // (void) memcpy(td->user_pin_sha, "00000000000000000000", SHA1_DIGEST_LENGTH); (void) memcpy(td->so_pin_sha, default_so_pin_sha, SHA1_DIGEST_LENGTH); (void) memset(user_pin_md5, 0x0, MD5_DIGEST_LENGTH); (void) memcpy(so_pin_md5, default_so_pin_md5, MD5_DIGEST_LENGTH); (void) memcpy(td->next_token_object_name, "00000000", 8); td->tweak_vector.allow_key_mods = TRUE; init_token_info(td); rc = token_get_tpm_info(hContext, td); if (rc != CKR_OK) return (rc); rc = save_token_data(td); return (rc); } // Function: compute_next_token_obj_name() // // Given a token object name (8 bytes in the range [0 - 9A - Z]) // increment by one adjusting as necessary // // This gives us a namespace of 36^8 = 2, 821, 109, 907, 456 // objects before wrapping around. // CK_RV compute_next_token_obj_name(CK_BYTE *current, CK_BYTE *next) { int val[8]; int i; if (! current || ! next) { return (CKR_FUNCTION_FAILED); } // Convert to integral base 36 // for (i = 0; i < 8; i++) { if (current[i] >= '0' && current[i] <= '9') val[i] = current[i] - '0'; if (current[i] >= 'A' && current[i] <= 'Z') val[i] = current[i] - 'A' + 10; } val[0]++; i = 0; while (val[i] > 35) { val[i] = 0; if (i + 1 < 8) { val[i + 1]++; i++; } else { val[0]++; i = 0; // start pass 2 } } // now, convert back to [0 - 9A - Z] // for (i = 0; i < 8; i++) { if (val[i] < 10) next[i] = '0' + val[i]; else next[i] = 'A' + val[i] - 10; } return (CKR_OK); } // // CK_RV build_attribute(CK_ATTRIBUTE_TYPE type, CK_BYTE *data, CK_ULONG data_len, CK_ATTRIBUTE **attrib) { CK_ATTRIBUTE *attr = NULL; attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + data_len); if (! attr) { return (CKR_DEVICE_MEMORY); } attr->type = type; attr->ulValueLen = data_len; if (data_len > 0) { attr->pValue = (CK_BYTE *)attr + sizeof (CK_ATTRIBUTE); (void) memcpy(attr->pValue, data, data_len); } else attr->pValue = NULL; *attrib = attr; return (CKR_OK); } CK_RV add_pkcs_padding(CK_BYTE * ptr, UINT32 block_size, UINT32 data_len, UINT32 total_len) { UINT32 i, pad_len; CK_BYTE pad_value; pad_len = block_size - (data_len % block_size); pad_value = (CK_BYTE)pad_len; if (data_len + pad_len > total_len) { return (CKR_FUNCTION_FAILED); } for (i = 0; i < pad_len; i++) ptr[i] = pad_value; return (CKR_OK); } CK_RV strip_pkcs_padding( CK_BYTE *ptr, UINT32 total_len, UINT32 *data_len) { CK_BYTE pad_value; pad_value = ptr[total_len - 1]; /* We have 'pad_value' bytes of 'pad_value' appended to the end */ *data_len = total_len - pad_value; return (CKR_OK); } CK_RV remove_leading_zeros(CK_ATTRIBUTE *attr) { CK_BYTE *ptr = NULL; CK_ULONG new_len, i; ptr = attr->pValue; for (i = 0; i < attr->ulValueLen; i++) { if (ptr[i] != 0x0) break; } new_len = attr->ulValueLen - i; (void) memcpy(ptr, ptr + i, new_len); attr->ulValueLen = new_len; return (CKR_OK); } CK_RV parity_is_odd(CK_BYTE b) { b = ((b >> 4) ^ b) & 0x0f; b = ((b >> 2) ^ b) & 0x03; b = ((b >> 1) ^ b) & 0x01; if (b == 1) return (TRUE); else return (FALSE); } CK_RV attach_shm() { if (global_shm != NULL) return (CKR_OK); global_shm = (LW_SHM_TYPE *)calloc(1, sizeof (LW_SHM_TYPE)); if (global_shm == NULL) { return (CKR_HOST_MEMORY); } CreateXProcLock(&global_shm->mutex); xproclock = (void *)&global_shm->mutex; return (CKR_OK); } CK_RV detach_shm() { if (global_shm != NULL) { free(global_shm); global_shm = NULL; } return (CKR_OK); } CK_RV compute_sha(CK_BYTE *data, CK_ULONG_32 len, CK_BYTE * hash) { SHA1_CTX ctx; SHA1Init(&ctx); SHA1Update(&ctx, data, len); SHA1Final(hash, &ctx); return (CKR_OK); } /* * The Initial Developer of the Original Code is International * Business Machines Corporation. Portions created by IBM * Corporation are Copyright (C) 2005 International Business * Machines Corporation. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the Common Public License as published by * IBM Corporation; either version 1 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * Common Public License for more details. * * You should have received a copy of the Common Public License * along with this program; if not, a copy can be viewed at * http://www.opensource.org/licenses/cpl1.0.php. */ /* (C) COPYRIGHT International Business Machines Corp. 2001, 2002, 2005 */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include "tpmtok_int.h" CK_RV verify_mgr_init(SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_MECHANISM * mech, CK_BBOOL recover_mode, CK_OBJECT_HANDLE key) { OBJECT * key_obj = NULL; CK_ATTRIBUTE * attr = NULL; CK_KEY_TYPE keytype; CK_OBJECT_CLASS class; CK_BBOOL flag; CK_RV rc; if (! sess || ! ctx) { return (CKR_FUNCTION_FAILED); } if (ctx->active != FALSE) { return (CKR_OPERATION_ACTIVE); } // key usage restrictions // rc = object_mgr_find_in_map1(sess->hContext, key, &key_obj); if (rc != CKR_OK) { return (CKR_KEY_HANDLE_INVALID); } // is key allowed to verify signatures? // rc = template_attribute_find(key_obj->template, CKA_VERIFY, &attr); if (rc == FALSE) { return (CKR_KEY_TYPE_INCONSISTENT); } else { flag = *(CK_BBOOL *)attr->pValue; if (flag != TRUE) { return (CKR_KEY_FUNCTION_NOT_PERMITTED); } } switch (mech->mechanism) { case CKM_RSA_PKCS: { rc = template_attribute_find(key_obj->template, CKA_KEY_TYPE, &attr); if (rc == FALSE) { return (CKR_KEY_TYPE_INCONSISTENT); } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_RSA) { return (CKR_KEY_TYPE_INCONSISTENT); } } flag = template_attribute_find(key_obj->template, CKA_CLASS, &attr); if (flag == FALSE) { return (CKR_FUNCTION_FAILED); } else class = *(CK_OBJECT_CLASS *)attr->pValue; if (class != CKO_PUBLIC_KEY) { return (CKR_FUNCTION_FAILED); } // PKCS #11 doesn't allow multi - part RSA operations ctx->context_len = 0; ctx->context = NULL; } break; case CKM_MD5_RSA_PKCS: case CKM_SHA1_RSA_PKCS: { rc = template_attribute_find(key_obj->template, CKA_KEY_TYPE, &attr); if (rc == FALSE) { return (CKR_KEY_TYPE_INCONSISTENT); } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_RSA) { return (CKR_KEY_TYPE_INCONSISTENT); } } flag = template_attribute_find(key_obj->template, CKA_CLASS, &attr); if (flag == FALSE) { return (CKR_FUNCTION_FAILED); } else class = *(CK_OBJECT_CLASS *)attr->pValue; if (class != CKO_PUBLIC_KEY) { return (CKR_FUNCTION_FAILED); } ctx->context_len = sizeof (RSA_DIGEST_CONTEXT); ctx->context = (CK_BYTE *)malloc( sizeof (RSA_DIGEST_CONTEXT)); if (! ctx->context) { return (CKR_HOST_MEMORY); } (void) memset(ctx->context, 0x0, sizeof (RSA_DIGEST_CONTEXT)); } break; case CKM_MD5_HMAC: case CKM_SHA_1_HMAC: { rc = template_attribute_find(key_obj->template, CKA_KEY_TYPE, &attr); if (rc == FALSE) { return (CKR_KEY_TYPE_INCONSISTENT); } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_GENERIC_SECRET) { return (CKR_KEY_TYPE_INCONSISTENT); } } // PKCS #11 doesn't allow multi - part HMAC operations ctx->context_len = 0; ctx->context = NULL; } break; case CKM_MD5_HMAC_GENERAL: case CKM_SHA_1_HMAC_GENERAL: { CK_MAC_GENERAL_PARAMS *param = (CK_MAC_GENERAL_PARAMS *)mech->pParameter; if (mech->ulParameterLen != sizeof (CK_MAC_GENERAL_PARAMS)) { return (CKR_MECHANISM_PARAM_INVALID); } if ((mech->mechanism == CKM_MD5_HMAC_GENERAL) && (*param > 16)) { return (CKR_MECHANISM_PARAM_INVALID); } if ((mech->mechanism == CKM_SHA_1_HMAC_GENERAL) && (*param > 20)) { return (CKR_MECHANISM_PARAM_INVALID); } rc = template_attribute_find(key_obj->template, CKA_KEY_TYPE, &attr); if (rc == FALSE) { return (CKR_KEY_TYPE_INCONSISTENT); } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_GENERIC_SECRET) { return (CKR_KEY_TYPE_INCONSISTENT); } } ctx->context_len = 0; ctx->context = NULL; } break; default: return (CKR_MECHANISM_INVALID); } ctx->key = key; ctx->mech.ulParameterLen = mech->ulParameterLen; ctx->mech.mechanism = mech->mechanism; ctx->mech.pParameter = mech->pParameter; ctx->multi = FALSE; ctx->active = TRUE; ctx->recover = recover_mode; return (CKR_OK); } CK_RV verify_mgr_cleanup(SIGN_VERIFY_CONTEXT *ctx) { if (! ctx) { return (CKR_FUNCTION_FAILED); } ctx->key = 0; ctx->mech.ulParameterLen = 0; ctx->mech.mechanism = 0; ctx->multi = FALSE; ctx->active = FALSE; ctx->recover = FALSE; ctx->context_len = 0; ctx->mech.pParameter = NULL; if (ctx->context) { free(ctx->context); ctx->context = NULL; } return (CKR_OK); } CK_RV verify_mgr_verify(SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * signature, CK_ULONG sig_len) { if (! sess || ! ctx) { return (CKR_FUNCTION_FAILED); } if (ctx->active == FALSE) { return (CKR_OPERATION_NOT_INITIALIZED); } if (ctx->recover == TRUE) { return (CKR_OPERATION_NOT_INITIALIZED); } if (! in_data || ! signature) { return (CKR_FUNCTION_FAILED); } if (ctx->multi == TRUE) { return (CKR_OPERATION_ACTIVE); } switch (ctx->mech.mechanism) { case CKM_RSA_PKCS: return (rsa_pkcs_verify(sess, ctx, in_data, in_data_len, signature, sig_len)); case CKM_MD5_RSA_PKCS: case CKM_SHA1_RSA_PKCS: return (rsa_hash_pkcs_verify(sess, ctx, in_data, in_data_len, signature, sig_len)); case CKM_MD5_HMAC: case CKM_MD5_HMAC_GENERAL: return (md5_hmac_verify(sess, ctx, in_data, in_data_len, signature, sig_len)); case CKM_SHA_1_HMAC: case CKM_SHA_1_HMAC_GENERAL: return (sha1_hmac_verify(sess, ctx, in_data, in_data_len, signature, sig_len)); default: return (CKR_MECHANISM_INVALID); } } CK_RV verify_mgr_verify_update(SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len) { if (! sess || ! ctx || ! in_data) { return (CKR_FUNCTION_FAILED); } if (ctx->active == FALSE) { return (CKR_OPERATION_NOT_INITIALIZED); } if (ctx->recover == TRUE) { return (CKR_OPERATION_NOT_INITIALIZED); } ctx->multi = TRUE; switch (ctx->mech.mechanism) { case CKM_MD5_RSA_PKCS: case CKM_SHA1_RSA_PKCS: return (rsa_hash_pkcs_verify_update(sess, ctx, in_data, in_data_len)); default: return (CKR_MECHANISM_INVALID); } } CK_RV verify_mgr_verify_final(SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * signature, CK_ULONG sig_len) { if (! sess || ! ctx) { return (CKR_FUNCTION_FAILED); } if (ctx->active == FALSE) { return (CKR_OPERATION_NOT_INITIALIZED); } if (ctx->recover == TRUE) { return (CKR_OPERATION_NOT_INITIALIZED); } switch (ctx->mech.mechanism) { case CKM_MD5_RSA_PKCS: case CKM_SHA1_RSA_PKCS: return (rsa_hash_pkcs_verify_final(sess, ctx, signature, sig_len)); default: return (CKR_MECHANISM_INVALID); } } CK_RV verify_mgr_verify_recover(SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * signature, CK_ULONG sig_len, CK_BYTE * out_data, CK_ULONG * out_len) { if (! sess || ! ctx) { return (CKR_FUNCTION_FAILED); } if (ctx->active == FALSE) { return (CKR_OPERATION_NOT_INITIALIZED); } if (ctx->recover == FALSE) { return (CKR_OPERATION_NOT_INITIALIZED); } if (! signature || ! out_len) { return (CKR_FUNCTION_FAILED); } if (ctx->multi == TRUE) { return (CKR_OPERATION_ACTIVE); } switch (ctx->mech.mechanism) { case CKM_RSA_PKCS: return (rsa_pkcs_verify_recover(sess, length_only, ctx, signature, sig_len, out_data, out_len)); default: return (CKR_MECHANISM_INVALID); } }