diff options
Diffstat (limited to 'security/tf_crypto_sst/pkcs11_global.c')
-rw-r--r-- | security/tf_crypto_sst/pkcs11_global.c | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/security/tf_crypto_sst/pkcs11_global.c b/security/tf_crypto_sst/pkcs11_global.c new file mode 100644 index 00000000..f7c491d7 --- /dev/null +++ b/security/tf_crypto_sst/pkcs11_global.c @@ -0,0 +1,275 @@ +/** + * Copyright(c) 2011 Trusted Logic. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Trusted Logic nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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 + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Implementation Notes: + * + * This API is NOT thread-safe. Indeed this Cryptoki implementation + * only supports option 1 defined in PKCS#11, section 6.5.2: + * "The application can specify that it will not be accessing the library concurrently + * from multiple threads, and so the library need not worry about performing any type + * of locking for the sake of thread-safety." + */ + +#include "pkcs11_internal.h" + +/* ------------------------------------------------------------------------ + System Service UUID +------------------------------------------------------------------------- */ +const TEEC_UUID SERVICE_UUID = SERVICE_SYSTEM_UUID; + +/* ------------------------------------------------------------------------ + Definition of the global TEE Context +------------------------------------------------------------------------- */ +TEEC_Context g_sContext; +/* A mutex that protects the access to the global context and to the + g_bContextRefCounter flag */ +LIB_MUTEX g_sContextMutex = LIB_MUTEX_INITIALIZER; +/* Whether the context has already been initialized or not */ +uint32_t g_nContextRefCounter = 0; + +bool g_bCryptokiInitialized = false; + +/* ------------------------------------------------------------------------ + Internal global TEE context management +------------------------------------------------------------------------- */ + +void stubMutexLock(void) +{ + libMutexLock(&g_sContextMutex); +} + +void stubMutexUnlock(void) +{ + libMutexUnlock(&g_sContextMutex); +} + +/* This API must be protected by stubMutexLock/Unlock */ +TEEC_Result stubInitializeContext(void) +{ + TEEC_Result nTeeError; + + if (g_nContextRefCounter) + { + g_nContextRefCounter ++; + return TEEC_SUCCESS; + } + + nTeeError = TEEC_InitializeContext(NULL, &g_sContext); + if (nTeeError == TEEC_SUCCESS) + { + g_nContextRefCounter = 1; + } + + return nTeeError; +} + +/* This API must be protected by stubMutexLock/Unlock */ +void stubFinalizeContext(void) +{ + if (g_nContextRefCounter > 0) + { + g_nContextRefCounter --; + } + + if (g_nContextRefCounter == 0) + { + TEEC_FinalizeContext(&g_sContext); + memset(&g_sContext, 0, sizeof(TEEC_Context)); + } +} + + +/* ------------------------------------------------------------------------ + Internal monitor management +------------------------------------------------------------------------- */ +/** +* Check that hSession is a valid primary session, +* or a valid secondary session attached to a valid primary session. +* +* input: +* S_HANDLE hSession: the session handle to check +* output: +* bool* pBoolIsPrimarySession: a boolean set to true if the session is primary, +* set to false if the session if the session is secondary +* returned boolean: set to true iff : +* - either hSession is a valid primary session +* - or hSession is a valid secondary session attached to a valid primary session +**/ +bool ckInternalSessionIsOpenedEx(S_HANDLE hSession, bool* pBoolIsPrimarySession) +{ + PPKCS11_SESSION_CONTEXT_HEADER pHeader = (PPKCS11_SESSION_CONTEXT_HEADER)hSession; + PPKCS11_PRIMARY_SESSION_CONTEXT pSession = NULL; + + if ((pHeader == NULL) || (pHeader->nMagicWord != PKCS11_SESSION_MAGIC)) + { + return FALSE; + } + if (pHeader->nSessionTag == PKCS11_PRIMARY_SESSION_TAG) /* primary session */ + { + pSession = (PPKCS11_PRIMARY_SESSION_CONTEXT)pHeader; + + *pBoolIsPrimarySession = true; + + /* check that primary session is valid */ + return (pSession->hCryptoSession != CK_INVALID_HANDLE); + } + else if (pHeader->nSessionTag == PKCS11_SECONDARY_SESSION_TAG) /*secondary session */ + { + PPKCS11_SECONDARY_SESSION_CONTEXT pSecSession = (PPKCS11_SECONDARY_SESSION_CONTEXT)pHeader; + + *pBoolIsPrimarySession = false; + + /* check that primary session is still valid */ + pSession = pSecSession->pPrimarySession; + if ( (pSession == NULL) || + (pSession->sHeader.nMagicWord != PKCS11_SESSION_MAGIC) || + (pSession->sHeader.nSessionTag != PKCS11_PRIMARY_SESSION_TAG)) + { + return FALSE; + } + + if (pSession->hCryptoSession == CK_INVALID_HANDLE) + { + return FALSE; + } + + /* check that secondary session is valid */ + return (pSecSession->hSecondaryCryptoSession != CK_INVALID_HANDLE); + } + else + { + return FALSE; + } +} + +/* ------------------------------------------------------------------------ + Internal error management +------------------------------------------------------------------------- */ + +CK_RV ckInternalTeeErrorToCKError(TEEC_Result nError) +{ + switch (nError) + { + case TEEC_SUCCESS: + return CKR_OK; + + case TEEC_ERROR_BAD_PARAMETERS: + case TEEC_ERROR_BAD_FORMAT: + return CKR_ARGUMENTS_BAD; + case TEEC_ERROR_OUT_OF_MEMORY: + return CKR_HOST_MEMORY; + case TEEC_ERROR_ACCESS_DENIED: + return CKR_TOKEN_NOT_PRESENT; + default: + return CKR_DEVICE_ERROR; + } +} + +/* ------------------------------------------------------------------------ + Public Functions +------------------------------------------------------------------------- */ +CK_RV PKCS11_EXPORT C_Initialize(CK_VOID_PTR pInitArgs) +{ + CK_RV nErrorCode; + TEEC_Result nTeeError; + + if (pInitArgs != NULL_PTR) + { + return CKR_ARGUMENTS_BAD; + } + + stubMutexLock(); + if (g_bCryptokiInitialized) + { + nErrorCode = CKR_CRYPTOKI_ALREADY_INITIALIZED; + } + else + { + nTeeError = stubInitializeContext(); + if (nTeeError == TEEC_SUCCESS) + { + g_bCryptokiInitialized = true; + } + nErrorCode = ckInternalTeeErrorToCKError(nTeeError); + } + stubMutexUnlock(); + + return nErrorCode; +} + +CK_RV PKCS11_EXPORT C_Finalize(CK_VOID_PTR pReserved) +{ + CK_RV nErrorCode; + + if (pReserved != NULL_PTR) + { + return CKR_ARGUMENTS_BAD; + } + + stubMutexLock(); + if (g_bCryptokiInitialized) + { + stubFinalizeContext(); + g_bCryptokiInitialized = false; + nErrorCode = CKR_OK; + } + else + { + nErrorCode = CKR_CRYPTOKI_NOT_INITIALIZED; + } + stubMutexUnlock(); + + return nErrorCode; +} + +static const CK_INFO sImplementationInfo = +{ + {2, 20}, /* cryptokiVersion, spec 2.20 */ + "Trusted Logic", /* manufacturerID */ + 0, /* flags */ + "PKCS#11", /* libraryDescription */ + {3, 0} /* libraryVersion */ +}; + +CK_RV PKCS11_EXPORT C_GetInfo(CK_INFO_PTR pInfo) +{ + if (!g_bCryptokiInitialized) + { + return CKR_CRYPTOKI_NOT_INITIALIZED; + } + if (pInfo == NULL_PTR) + { + return CKR_ARGUMENTS_BAD; + } + + memcpy(pInfo, &sImplementationInfo, sizeof(CK_INFO)); + return CKR_OK; +} |