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 ------------------------------------------------------------------------- */ 46 const TEEC_UUID SERVICE_UUID = SERVICE_SYSTEM_UUID; 47 48 /* ------------------------------------------------------------------------ 49 Definition of the global TEE Context 50 ------------------------------------------------------------------------- */ 51 TEEC_Context g_sContext; 52 /* A mutex that protects the access to the global context and to the 53 g_bContextRefCounter flag */ 54 LIB_MUTEX g_sContextMutex = LIB_MUTEX_INITIALIZER; 55 /* Whether the context has already been initialized or not */ 56 uint32_t g_nContextRefCounter = 0; 57 58 bool g_bCryptokiInitialized = false; 59 60 /* ------------------------------------------------------------------------ 61 Internal global TEE context management 62 ------------------------------------------------------------------------- */ 63 64 void stubMutexLock(void) 65 { 66 libMutexLock(&g_sContextMutex); 67 } 68 69 void stubMutexUnlock(void) 70 { 71 libMutexUnlock(&g_sContextMutex); 72 } 73 74 /* This API must be protected by stubMutexLock/Unlock */ 75 TEEC_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 */ 95 void 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 **/ 126 bool 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 177 CK_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 ------------------------------------------------------------------------- */ 199 CK_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 228 CK_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 253 static 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 262 CK_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