1/** 2 * Copyright(c) 2011 Trusted Logic. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in 12 * the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name Trusted Logic nor the names of its 15 * contributors may be used to endorse or promote products derived 16 * from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31/* 32 * Implementation Notes: 33 * 34 * This API is NOT thread-safe. Indeed this Cryptoki implementation 35 * only supports option 1 defined in PKCS#11, section 6.5.2: 36 * "The application can specify that it will not be accessing the library concurrently 37 * from multiple threads, and so the library need not worry about performing any type 38 * of locking for the sake of thread-safety." 39 */ 40 41#include "pkcs11_internal.h" 42 43/* ------------------------------------------------------------------------ 44 System Service UUID 45------------------------------------------------------------------------- */ 46const TEEC_UUID SERVICE_UUID = SERVICE_SYSTEM_UUID; 47 48/* ------------------------------------------------------------------------ 49 Definition of the global TEE Context 50------------------------------------------------------------------------- */ 51TEEC_Context g_sContext; 52/* A mutex that protects the access to the global context and to the 53 g_bContextRefCounter flag */ 54LIB_MUTEX g_sContextMutex = LIB_MUTEX_INITIALIZER; 55/* Whether the context has already been initialized or not */ 56uint32_t g_nContextRefCounter = 0; 57 58bool g_bCryptokiInitialized = false; 59 60/* ------------------------------------------------------------------------ 61 Internal global TEE context management 62------------------------------------------------------------------------- */ 63 64void stubMutexLock(void) 65{ 66 libMutexLock(&g_sContextMutex); 67} 68 69void stubMutexUnlock(void) 70{ 71 libMutexUnlock(&g_sContextMutex); 72} 73 74/* This API must be protected by stubMutexLock/Unlock */ 75TEEC_Result stubInitializeContext(void) 76{ 77 TEEC_Result nTeeError; 78 79 if (g_nContextRefCounter) 80 { 81 g_nContextRefCounter ++; 82 return TEEC_SUCCESS; 83 } 84 85 nTeeError = TEEC_InitializeContext(NULL, &g_sContext); 86 if (nTeeError == TEEC_SUCCESS) 87 { 88 g_nContextRefCounter = 1; 89 } 90 91 return nTeeError; 92} 93 94/* This API must be protected by stubMutexLock/Unlock */ 95void stubFinalizeContext(void) 96{ 97 if (g_nContextRefCounter > 0) 98 { 99 g_nContextRefCounter --; 100 } 101 102 if (g_nContextRefCounter == 0) 103 { 104 TEEC_FinalizeContext(&g_sContext); 105 memset(&g_sContext, 0, sizeof(TEEC_Context)); 106 } 107} 108 109 110/* ------------------------------------------------------------------------ 111 Internal monitor management 112------------------------------------------------------------------------- */ 113/** 114* Check that hSession is a valid primary session, 115* or a valid secondary session attached to a valid primary session. 116* 117* input: 118* S_HANDLE hSession: the session handle to check 119* output: 120* bool* pBoolIsPrimarySession: a boolean set to true if the session is primary, 121* set to false if the session if the session is secondary 122* returned boolean: set to true iff : 123* - either hSession is a valid primary session 124* - or hSession is a valid secondary session attached to a valid primary session 125**/ 126bool ckInternalSessionIsOpenedEx(S_HANDLE hSession, bool* pBoolIsPrimarySession) 127{ 128 PPKCS11_SESSION_CONTEXT_HEADER pHeader = (PPKCS11_SESSION_CONTEXT_HEADER)hSession; 129 PPKCS11_PRIMARY_SESSION_CONTEXT pSession = NULL; 130 131 if ((pHeader == NULL) || (pHeader->nMagicWord != PKCS11_SESSION_MAGIC)) 132 { 133 return FALSE; 134 } 135 if (pHeader->nSessionTag == PKCS11_PRIMARY_SESSION_TAG) /* primary session */ 136 { 137 pSession = (PPKCS11_PRIMARY_SESSION_CONTEXT)pHeader; 138 139 *pBoolIsPrimarySession = true; 140 141 /* check that primary session is valid */ 142 return (pSession->hCryptoSession != CK_INVALID_HANDLE); 143 } 144 else if (pHeader->nSessionTag == PKCS11_SECONDARY_SESSION_TAG) /*secondary session */ 145 { 146 PPKCS11_SECONDARY_SESSION_CONTEXT pSecSession = (PPKCS11_SECONDARY_SESSION_CONTEXT)pHeader; 147 148 *pBoolIsPrimarySession = false; 149 150 /* check that primary session is still valid */ 151 pSession = pSecSession->pPrimarySession; 152 if ( (pSession == NULL) || 153 (pSession->sHeader.nMagicWord != PKCS11_SESSION_MAGIC) || 154 (pSession->sHeader.nSessionTag != PKCS11_PRIMARY_SESSION_TAG)) 155 { 156 return FALSE; 157 } 158 159 if (pSession->hCryptoSession == CK_INVALID_HANDLE) 160 { 161 return FALSE; 162 } 163 164 /* check that secondary session is valid */ 165 return (pSecSession->hSecondaryCryptoSession != CK_INVALID_HANDLE); 166 } 167 else 168 { 169 return FALSE; 170 } 171} 172 173/* ------------------------------------------------------------------------ 174 Internal error management 175------------------------------------------------------------------------- */ 176 177CK_RV ckInternalTeeErrorToCKError(TEEC_Result nError) 178{ 179 switch (nError) 180 { 181 case TEEC_SUCCESS: 182 return CKR_OK; 183 184 case TEEC_ERROR_BAD_PARAMETERS: 185 case TEEC_ERROR_BAD_FORMAT: 186 return CKR_ARGUMENTS_BAD; 187 case TEEC_ERROR_OUT_OF_MEMORY: 188 return CKR_HOST_MEMORY; 189 case TEEC_ERROR_ACCESS_DENIED: 190 return CKR_TOKEN_NOT_PRESENT; 191 default: 192 return CKR_DEVICE_ERROR; 193 } 194} 195 196/* ------------------------------------------------------------------------ 197 Public Functions 198------------------------------------------------------------------------- */ 199CK_RV PKCS11_EXPORT C_Initialize(CK_VOID_PTR pInitArgs) 200{ 201 CK_RV nErrorCode; 202 TEEC_Result nTeeError; 203 204 if (pInitArgs != NULL_PTR) 205 { 206 return CKR_ARGUMENTS_BAD; 207 } 208 209 stubMutexLock(); 210 if (g_bCryptokiInitialized) 211 { 212 nErrorCode = CKR_CRYPTOKI_ALREADY_INITIALIZED; 213 } 214 else 215 { 216 nTeeError = stubInitializeContext(); 217 if (nTeeError == TEEC_SUCCESS) 218 { 219 g_bCryptokiInitialized = true; 220 } 221 nErrorCode = ckInternalTeeErrorToCKError(nTeeError); 222 } 223 stubMutexUnlock(); 224 225 return nErrorCode; 226} 227 228CK_RV PKCS11_EXPORT C_Finalize(CK_VOID_PTR pReserved) 229{ 230 CK_RV nErrorCode; 231 232 if (pReserved != NULL_PTR) 233 { 234 return CKR_ARGUMENTS_BAD; 235 } 236 237 stubMutexLock(); 238 if (g_bCryptokiInitialized) 239 { 240 stubFinalizeContext(); 241 g_bCryptokiInitialized = false; 242 nErrorCode = CKR_OK; 243 } 244 else 245 { 246 nErrorCode = CKR_CRYPTOKI_NOT_INITIALIZED; 247 } 248 stubMutexUnlock(); 249 250 return nErrorCode; 251} 252 253static const CK_INFO sImplementationInfo = 254{ 255 {2, 20}, /* cryptokiVersion, spec 2.20 */ 256 "Trusted Logic", /* manufacturerID */ 257 0, /* flags */ 258 "PKCS#11", /* libraryDescription */ 259 {3, 0} /* libraryVersion */ 260}; 261 262CK_RV PKCS11_EXPORT C_GetInfo(CK_INFO_PTR pInfo) 263{ 264 if (!g_bCryptokiInitialized) 265 { 266 return CKR_CRYPTOKI_NOT_INITIALIZED; 267 } 268 if (pInfo == NULL_PTR) 269 { 270 return CKR_ARGUMENTS_BAD; 271 } 272 273 memcpy(pInfo, &sImplementationInfo, sizeof(CK_INFO)); 274 return CKR_OK; 275} 276