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
stubMutexLock(void)64 void stubMutexLock(void)
65 {
66 libMutexLock(&g_sContextMutex);
67 }
68
stubMutexUnlock(void)69 void stubMutexUnlock(void)
70 {
71 libMutexUnlock(&g_sContextMutex);
72 }
73
74 /* This API must be protected by stubMutexLock/Unlock */
stubInitializeContext(void)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 */
stubFinalizeContext(void)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 **/
ckInternalSessionIsOpenedEx(S_HANDLE hSession,bool * pBoolIsPrimarySession)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
ckInternalTeeErrorToCKError(TEEC_Result nError)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 ------------------------------------------------------------------------- */
C_Initialize(CK_VOID_PTR pInitArgs)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
C_Finalize(CK_VOID_PTR pReserved)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
C_GetInfo(CK_INFO_PTR pInfo)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