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
C_OpenSession(CK_SLOT_ID slotID,CK_FLAGS flags,CK_VOID_PTR pApplication,CK_NOTIFY Notify,CK_SESSION_HANDLE * phSession)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
C_CloseSession(CK_SESSION_HANDLE hSession)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
C_Login(CK_SESSION_HANDLE hSession,CK_USER_TYPE userType,const CK_UTF8CHAR * pPin,CK_ULONG ulPinLen)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
C_Logout(CK_SESSION_HANDLE hSession)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