/* * 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) { _init(); 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); } }