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 * The PKCS11 session handle is directly mapped on the 35 * Trusted Foundations Software session handle (S_HANDLE). 36 */ 37 38 #include "pkcs11_internal.h" 39 40 41 /* ------------------------------------------------------------------------ 42 Public Functions 43 ------------------------------------------------------------------------- */ 44 45 46 CK_RV PKCS11_EXPORT C_OpenSession(CK_SLOT_ID slotID, /* the slot's ID */ 47 CK_FLAGS flags, /* defined in CK_SESSION_INFO */ 48 CK_VOID_PTR pApplication, /* pointer passed to callback */ 49 CK_NOTIFY Notify, /* notification callback function */ 50 CK_SESSION_HANDLE* phSession) /* receives new session handle */ 51 { 52 CK_RV nErrorCode = CKR_OK; 53 uint32_t nErrorOrigin = TEEC_ORIGIN_API; 54 TEEC_Result nTeeError; 55 TEEC_Operation sOperation; 56 PPKCS11_PRIMARY_SESSION_CONTEXT pSession = NULL; 57 PPKCS11_SECONDARY_SESSION_CONTEXT pSecondarySession = NULL; 58 uint32_t nLoginType; 59 uint32_t nLoginData = 0; 60 void* pLoginData = NULL; 61 bool bIsPrimarySession; 62 char* pSignatureFile = NULL; 63 uint32_t nSignatureFileLen = 0; 64 uint8_t nParamType3 = TEEC_NONE; 65 66 /* Prevent the compiler from complaining about unused parameters */ 67 do{(void)pApplication;}while(0); 68 do{(void)Notify;}while(0); 69 70 if (phSession == NULL) 71 { 72 return CKR_ARGUMENTS_BAD; 73 } 74 75 /* Check Cryptoki is initialized */ 76 if (!g_bCryptokiInitialized) 77 { 78 return CKR_CRYPTOKI_NOT_INITIALIZED; 79 } 80 81 if ((flags & CKVF_OPEN_SUB_SESSION) == 0) 82 { 83 *phSession = CK_INVALID_HANDLE; 84 85 /* 86 * Allocate the session context 87 */ 88 pSession = (PPKCS11_PRIMARY_SESSION_CONTEXT)malloc(sizeof(PKCS11_PRIMARY_SESSION_CONTEXT)); 89 if (pSession == NULL) 90 { 91 return CKR_DEVICE_MEMORY; 92 } 93 94 pSession->sHeader.nMagicWord = PKCS11_SESSION_MAGIC; 95 pSession->sHeader.nSessionTag = PKCS11_PRIMARY_SESSION_TAG; 96 memset(&pSession->sSession, 0, sizeof(TEEC_Session)); 97 pSession->sSecondarySessionTable.pRoot = NULL_PTR; 98 99 /* The structure must be initialized first (in a portable manner) 100 to make it work on Win32 */ 101 memset(&pSession->sSecondarySessionTableMutex, 0, 102 sizeof(pSession->sSecondarySessionTableMutex)); 103 libMutexInit(&pSession->sSecondarySessionTableMutex); 104 105 switch (slotID) 106 { 107 case CKV_TOKEN_SYSTEM_SHARED: 108 case CKV_TOKEN_USER_SHARED: 109 nLoginType = TEEC_LOGIN_PUBLIC; 110 break; 111 112 case CKV_TOKEN_SYSTEM: 113 case CKV_TOKEN_USER: 114 default: 115 nLoginType = TEEC_LOGIN_AUTHENTICATION; 116 break; 117 } 118 119 /* Group tokens */ 120 if ((slotID >= 0x00010000) && (slotID <= 0x0002FFFF)) 121 { 122 nLoginType = TEEC_LOGIN_GROUP; 123 124 /* The 16 lower-order bits encode the group identifier */ 125 nLoginData = (uint32_t)slotID & 0x0000FFFF; 126 pLoginData = (void*)&nLoginData; 127 128 /* Update the slotID for the system / PKCS11 service */ 129 if ((slotID >= 0x00010000) && (slotID <= 0x0001FFFF)) 130 { 131 /* System group token */ 132 slotID = 3; /* CKV_TOKEN_SYSTEM_GROUP */ 133 } 134 else /* ((slotID >= 0x00020000) && (slotID <= 0x0002FFFF)) */ 135 { 136 /* User group token */ 137 slotID = 0x4014; /* CKV_TOKEN_USER_GROUP */ 138 } 139 } 140 141 retry: 142 memset(&sOperation, 0, sizeof(TEEC_Operation)); 143 144 if (nLoginType == TEEC_LOGIN_AUTHENTICATION) 145 { 146 nTeeError = TEEC_ReadSignatureFile((void **)&pSignatureFile, &nSignatureFileLen); 147 if (nTeeError != TEEC_ERROR_ITEM_NOT_FOUND) 148 { 149 if (nTeeError != TEEC_SUCCESS) 150 { 151 goto error; 152 } 153 154 sOperation.params[3].tmpref.buffer = pSignatureFile; 155 sOperation.params[3].tmpref.size = nSignatureFileLen; 156 nParamType3 = TEEC_MEMREF_TEMP_INPUT; 157 } 158 else 159 { 160 /* No signature file found. 161 * Should use LOGIN_APPLICATION for now 162 * Can not use TEEC_LOGIN_AUTHENTICATION as this means that all .exe wil need a signature file 163 * - a bit annoying for when passing the tests 164 */ 165 nLoginType = TEEC_LOGIN_USER_APPLICATION; 166 } 167 } 168 169 sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, nParamType3); 170 nTeeError = TEEC_OpenSession(&g_sContext, 171 &pSession->sSession, /* OUT session */ 172 &SERVICE_UUID, /* destination UUID */ 173 nLoginType, /* connectionMethod */ 174 pLoginData, /* connectionData */ 175 &sOperation, /* IN OUT operation */ 176 NULL /* OUT returnOrigin, optional */ 177 ); 178 if (nTeeError != TEEC_SUCCESS) 179 { 180 /* No need of the returnOrigin as this is not specific to P11 */ 181 182 if ( (nTeeError == TEEC_ERROR_NOT_SUPPORTED) && 183 (nLoginType == TEEC_LOGIN_AUTHENTICATION)) 184 { 185 /* We could not open a session with the login TEEC_LOGIN_AUTHENTICATION */ 186 /* If it is not supported by the product, */ 187 /* retry with fallback to TEEC_LOGIN_USER_APPLICATION */ 188 nLoginType = TEEC_LOGIN_USER_APPLICATION; 189 goto retry; 190 } 191 192 /* The ERROR_ACCESS_DENIED, if returned, will be converted into CKR_TOKEN_NOT_PRESENT 193 * For the External Cryptographic API, this means that the authentication 194 * of the calling application fails. 195 */ 196 goto error; 197 } 198 199 memset(&sOperation, 0, sizeof(TEEC_Operation)); 200 sOperation.params[0].value.a = slotID; 201 sOperation.params[0].value.b = flags; /* access flags */ 202 sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_NONE, TEEC_NONE, TEEC_NONE); 203 nTeeError = TEEC_InvokeCommand(&pSession->sSession, 204 SERVICE_SYSTEM_PKCS11_C_OPEN_SESSION_COMMAND_ID & 0x00007FFF, 205 &sOperation, /* IN OUT operation */ 206 &nErrorOrigin /* OUT returnOrigin, optional */ 207 ); 208 if (nTeeError != TEEC_SUCCESS) 209 { 210 goto error; 211 } 212 213 *phSession = (CK_SESSION_HANDLE)pSession; 214 pSession->hCryptoSession = sOperation.params[0].value.a; 215 216 return CKR_OK; 217 } 218 else 219 { 220 bool bResult; 221 222 /* Check that {*phSession} is a valid primary session handle */ 223 if ((!ckInternalSessionIsOpenedEx(*phSession, &bIsPrimarySession)) || 224 (!bIsPrimarySession)) 225 { 226 return CKR_SESSION_HANDLE_INVALID; 227 } 228 229 pSession = (PPKCS11_PRIMARY_SESSION_CONTEXT)(*phSession); 230 231 /* allocate the secondary session context */ 232 pSecondarySession = (PKCS11_SECONDARY_SESSION_CONTEXT*)malloc(sizeof(PKCS11_SECONDARY_SESSION_CONTEXT)); 233 if (pSecondarySession == NULL) 234 { 235 return CKR_DEVICE_MEMORY; 236 } 237 pSecondarySession->sHeader.nMagicWord = PKCS11_SESSION_MAGIC; 238 pSecondarySession->sHeader.nSessionTag = PKCS11_SECONDARY_SESSION_TAG; 239 pSecondarySession->pPrimarySession = pSession; 240 241 libMutexLock(&pSession->sSecondarySessionTableMutex); 242 bResult = libObjectHandle16Add(&pSession->sSecondarySessionTable, 243 &pSecondarySession->sSecondarySessionNode); 244 libMutexUnlock(&pSession->sSecondarySessionTableMutex); 245 if (bResult == false) 246 { 247 free(pSecondarySession); 248 return CKR_DEVICE_MEMORY; 249 } 250 251 memset(&sOperation, 0, sizeof(TEEC_Operation)); 252 sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_NONE, TEEC_NONE, TEEC_NONE); 253 nTeeError = TEEC_InvokeCommand(&pSession->sSession, 254 (pSession->hCryptoSession << 16) | 255 (1 << 15) | 256 (SERVICE_SYSTEM_PKCS11_C_OPEN_SESSION_COMMAND_ID & 0x00007FFF), 257 &sOperation, /* IN OUT operation */ 258 &nErrorOrigin /* OUT returnOrigin, optional */ 259 ); 260 if (nTeeError != TEEC_SUCCESS) 261 { 262 goto error; 263 } 264 265 *phSession = (CK_SESSION_HANDLE)pSecondarySession; 266 pSecondarySession->hSecondaryCryptoSession = sOperation.params[0].value.a; 267 268 return CKR_OK; 269 } 270 271 error: 272 nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ? 273 nTeeError : 274 ckInternalTeeErrorToCKError(nTeeError)); 275 276 if ((flags & CKVF_OPEN_SUB_SESSION) == 0) 277 { 278 libMutexDestroy(&pSession->sSecondarySessionTableMutex); 279 free(pSession); 280 } 281 else 282 { 283 libMutexLock(&pSession->sSecondarySessionTableMutex); 284 libObjectHandle16Remove(&pSession->sSecondarySessionTable,&pSecondarySession->sSecondarySessionNode); 285 libMutexUnlock(&pSession->sSecondarySessionTableMutex); 286 free(pSecondarySession); 287 } 288 289 return nErrorCode; 290 } 291 292 CK_RV PKCS11_EXPORT C_CloseSession(CK_SESSION_HANDLE hSession) /* the session's handle */ 293 { 294 CK_RV nErrorCode = CKR_OK; 295 uint32_t nErrorOrigin = TEEC_ORIGIN_API; 296 TEEC_Result nTeeError; 297 TEEC_Operation sOperation; 298 bool bIsPrimarySession; 299 300 /* Check Cryptoki is initialized */ 301 if (!g_bCryptokiInitialized) 302 { 303 return CKR_CRYPTOKI_NOT_INITIALIZED; 304 } 305 306 if (!ckInternalSessionIsOpenedEx(hSession, &bIsPrimarySession)) 307 { 308 return CKR_SESSION_HANDLE_INVALID; 309 } 310 311 if (bIsPrimarySession) 312 { 313 LIB_OBJECT_NODE_HANDLE16* pObject; 314 PPKCS11_SECONDARY_SESSION_CONTEXT pSecSession; 315 PPKCS11_PRIMARY_SESSION_CONTEXT pSession = (PPKCS11_PRIMARY_SESSION_CONTEXT)hSession; 316 317 hSession = pSession->hCryptoSession; 318 319 memset(&sOperation, 0, sizeof(TEEC_Operation)); 320 sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE); 321 nTeeError = TEEC_InvokeCommand(&pSession->sSession, 322 (pSession->hCryptoSession << 16 ) | 323 (SERVICE_SYSTEM_PKCS11_C_CLOSE_SESSION_COMMAND_ID & 0x00007FFF), 324 &sOperation, /* IN OUT operation */ 325 &nErrorOrigin /* OUT returnOrigin, optional */ 326 ); 327 if (nTeeError != TEEC_SUCCESS) 328 { 329 goto end; 330 } 331 332 TEEC_CloseSession(&pSession->sSession); 333 memset(&pSession->sSession, 0, sizeof(TEEC_Session)); 334 335 /* Free all secondary session contexts */ 336 libMutexLock(&pSession->sSecondarySessionTableMutex); 337 pObject = libObjectHandle16RemoveOne(&pSession->sSecondarySessionTable); 338 while (pObject != NULL) 339 { 340 /* find all secondary session contexts, 341 and release associated resources */ 342 343 pSecSession = LIB_OBJECT_CONTAINER_OF(pObject, //ptr 344 PKCS11_SECONDARY_SESSION_CONTEXT,//type 345 sSecondarySessionNode);//member 346 347 /* free secondary session context */ 348 free(pSecSession); 349 350 pObject = libObjectHandle16RemoveOne(&pSession->sSecondarySessionTable); 351 } 352 libMutexUnlock(&pSession->sSecondarySessionTableMutex); 353 354 libMutexDestroy(&pSession->sSecondarySessionTableMutex); 355 356 /* free primary session context */ 357 free(pSession); 358 } 359 else 360 { 361 PPKCS11_SECONDARY_SESSION_CONTEXT pSecSession = (PPKCS11_SECONDARY_SESSION_CONTEXT)hSession; 362 PPKCS11_PRIMARY_SESSION_CONTEXT pSession; 363 364 uint32_t nCommandID = ( (pSecSession->hSecondaryCryptoSession & 0xFFFF) << 16 ) | 365 (1 << 15) | 366 (SERVICE_SYSTEM_PKCS11_C_CLOSE_SESSION_COMMAND_ID & 0x00007FFF); 367 368 /* every pre-check are fine, then, update the local handles */ 369 hSession = pSecSession->pPrimarySession->hCryptoSession; 370 pSession = (PPKCS11_PRIMARY_SESSION_CONTEXT)(pSecSession->pPrimarySession); 371 372 memset(&sOperation, 0, sizeof(TEEC_Operation)); 373 sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE); 374 nTeeError = TEEC_InvokeCommand(&pSession->sSession, 375 nCommandID, 376 &sOperation, /* IN OUT operation */ 377 &nErrorOrigin /* OUT returnOrigin, optional */ 378 ); 379 if (nTeeError != TEEC_SUCCESS) 380 { 381 goto end; 382 } 383 384 /* remove the object from the table */ 385 libMutexLock(&pSession->sSecondarySessionTableMutex); 386 libObjectHandle16Remove(&pSecSession->pPrimarySession->sSecondarySessionTable, &pSecSession->sSecondarySessionNode); 387 libMutexUnlock(&pSession->sSecondarySessionTableMutex); 388 389 /* free secondary session context */ 390 free(pSecSession); 391 } 392 393 end: 394 nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ? 395 nTeeError : 396 ckInternalTeeErrorToCKError(nTeeError)); 397 return nErrorCode; 398 } 399 400 401 CK_RV PKCS11_EXPORT C_Login(CK_SESSION_HANDLE hSession, /* the session's handle */ 402 CK_USER_TYPE userType, /* the user type */ 403 const CK_UTF8CHAR* pPin, /* the user's PIN */ 404 CK_ULONG ulPinLen) /* the length of the PIN */ 405 { 406 /* Prevent the compiler from complaining about unused variables */ 407 do{(void)hSession;}while(0); 408 do{(void)userType;}while(0); 409 do{(void)pPin;}while(0); 410 do{(void)ulPinLen;}while(0); 411 412 return CKR_OK; 413 } 414 415 CK_RV PKCS11_EXPORT C_Logout(CK_SESSION_HANDLE hSession) /* the session's handle */ 416 { 417 do{(void)hSession;}while(0); 418 419 return CKR_OK; 420 } 421