1 | /* |
2 | * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. |
3 | */ |
4 | |
5 | /* Copyright (c) 2002 Graz University of Technology. All rights reserved. |
6 | * |
7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions are met: |
9 | * |
10 | * 1. Redistributions of source code must retain the above copyright notice, |
11 | * this list of conditions and the following disclaimer. |
12 | * |
13 | * 2. Redistributions in binary form must reproduce the above copyright notice, |
14 | * this list of conditions and the following disclaimer in the documentation |
15 | * and/or other materials provided with the distribution. |
16 | * |
17 | * 3. The end-user documentation included with the redistribution, if any, must |
18 | * include the following acknowledgment: |
19 | * |
20 | * "This product includes software developed by IAIK of Graz University of |
21 | * Technology." |
22 | * |
23 | * Alternately, this acknowledgment may appear in the software itself, if |
24 | * and wherever such third-party acknowledgments normally appear. |
25 | * |
26 | * 4. The names "Graz University of Technology" and "IAIK of Graz University of |
27 | * Technology" must not be used to endorse or promote products derived from |
28 | * this software without prior written permission. |
29 | * |
30 | * 5. Products derived from this software may not be called |
31 | * "IAIK PKCS Wrapper", nor may "IAIK" appear in their name, without prior |
32 | * written permission of Graz University of Technology. |
33 | * |
34 | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED |
35 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
36 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
37 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE |
38 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, |
39 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
40 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, |
41 | * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON |
42 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
43 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
44 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
45 | * POSSIBILITY OF SUCH DAMAGE. |
46 | */ |
47 | |
48 | #include "pkcs11wrapper.h" |
49 | |
50 | #include <stdio.h> |
51 | #include <stdlib.h> |
52 | #include <string.h> |
53 | #include <assert.h> |
54 | |
55 | #include "sun_security_pkcs11_wrapper_PKCS11.h" |
56 | |
57 | /* The initArgs that enable the application to do custom mutex-handling */ |
58 | #ifndef NO_CALLBACKS |
59 | jobject jInitArgsObject; |
60 | CK_C_INITIALIZE_ARGS_PTR ckpGlobalInitArgs; |
61 | #endif /* NO_CALLBACKS */ |
62 | |
63 | /* ************************************************************************** */ |
64 | /* Now come the functions for mutex handling and notification callbacks */ |
65 | /* ************************************************************************** */ |
66 | |
67 | /* |
68 | * converts the InitArgs object to a CK_C_INITIALIZE_ARGS structure and sets the functions |
69 | * that will call the right Java mutex functions |
70 | * |
71 | * @param env - used to call JNI funktions to get the Java classes, objects, methods and fields |
72 | * @param pInitArgs - the InitArgs object with the Java mutex functions to call |
73 | * @return - the pointer to the CK_C_INITIALIZE_ARGS structure with the functions that will call |
74 | * the corresponding Java functions |
75 | */ |
76 | CK_C_INITIALIZE_ARGS_PTR makeCKInitArgsAdapter(JNIEnv *env, jobject jInitArgs) |
77 | { |
78 | CK_C_INITIALIZE_ARGS_PTR ckpInitArgs; |
79 | jclass jInitArgsClass; |
80 | jfieldID fieldID; |
81 | jlong jFlags; |
82 | jobject jReserved; |
83 | CK_ULONG ckReservedLength; |
84 | #ifndef NO_CALLBACKS |
85 | jobject jMutexHandler; |
86 | #endif /* NO_CALLBACKS */ |
87 | |
88 | if(jInitArgs == NULL) { |
89 | return NULL_PTR; |
90 | } |
91 | |
92 | /* convert the Java InitArgs object to a pointer to a CK_C_INITIALIZE_ARGS structure */ |
93 | ckpInitArgs = (CK_C_INITIALIZE_ARGS_PTR) malloc(sizeof(CK_C_INITIALIZE_ARGS)); |
94 | if (ckpInitArgs == NULL) { |
95 | throwOutOfMemoryError(env, 0); |
96 | return NULL_PTR; |
97 | } |
98 | ckpInitArgs->flags = (CK_FLAGS)0; |
99 | ckpInitArgs->pReserved = (CK_VOID_PTR)NULL; |
100 | |
101 | /* Set the mutex functions that will call the Java mutex functions, but |
102 | * only set it, if the field is not null. |
103 | */ |
104 | jInitArgsClass = (*env)->FindClass(env, CLASS_C_INITIALIZE_ARGS); |
105 | if (jInitArgsClass == NULL) { |
106 | free(ckpInitArgs); |
107 | return NULL; |
108 | } |
109 | |
110 | #ifdef NO_CALLBACKS |
111 | ckpInitArgs->CreateMutex = NULL_PTR; |
112 | ckpInitArgs->DestroyMutex = NULL_PTR; |
113 | ckpInitArgs->LockMutex = NULL_PTR; |
114 | ckpInitArgs->UnlockMutex = NULL_PTR; |
115 | #else |
116 | fieldID = (*env)->GetFieldID(env, jInitArgsClass, "CreateMutex" , "Lsun/security/pkcs11/wrapper/CK_CREATEMUTEX;" ); |
117 | if (fieldID == NULL) { |
118 | free(ckpInitArgs); |
119 | return NULL; |
120 | } |
121 | jMutexHandler = (*env)->GetObjectField(env, jInitArgs, fieldID); |
122 | ckpInitArgs->CreateMutex = (jMutexHandler != NULL) ? &callJCreateMutex : NULL_PTR; |
123 | |
124 | fieldID = (*env)->GetFieldID(env, jInitArgsClass, "DestroyMutex" , "Lsun/security/pkcs11/wrapper/CK_DESTROYMUTEX;" ); |
125 | if (fieldID == NULL) { |
126 | free(ckpInitArgs); |
127 | return NULL; |
128 | } |
129 | jMutexHandler = (*env)->GetObjectField(env, jInitArgs, fieldID); |
130 | ckpInitArgs->DestroyMutex = (jMutexHandler != NULL) ? &callJDestroyMutex : NULL_PTR; |
131 | |
132 | fieldID = (*env)->GetFieldID(env, jInitArgsClass, "LockMutex" , "Lsun/security/pkcs11/wrapper/CK_LOCKMUTEX;" ); |
133 | if (fieldID == NULL) { |
134 | free(ckpInitArgs); |
135 | return NULL; |
136 | } |
137 | jMutexHandler = (*env)->GetObjectField(env, jInitArgs, fieldID); |
138 | ckpInitArgs->LockMutex = (jMutexHandler != NULL) ? &callJLockMutex : NULL_PTR; |
139 | |
140 | fieldID = (*env)->GetFieldID(env, jInitArgsClass, "UnlockMutex" , "Lsun/security/pkcs11/wrapper/CK_UNLOCKMUTEX;" ); |
141 | if (fieldID == NULL) { |
142 | free(ckpInitArgs); |
143 | return NULL; |
144 | } |
145 | jMutexHandler = (*env)->GetObjectField(env, jInitArgs, fieldID); |
146 | ckpInitArgs->UnlockMutex = (jMutexHandler != NULL) ? &callJUnlockMutex : NULL_PTR; |
147 | |
148 | if ((ckpInitArgs->CreateMutex != NULL_PTR) |
149 | || (ckpInitArgs->DestroyMutex != NULL_PTR) |
150 | || (ckpInitArgs->LockMutex != NULL_PTR) |
151 | || (ckpInitArgs->UnlockMutex != NULL_PTR)) { |
152 | /* we only need to keep a global copy, if we need callbacks */ |
153 | /* set the global object jInitArgs so that the right Java mutex functions will be called */ |
154 | jInitArgsObject = (*env)->NewGlobalRef(env, jInitArgs); |
155 | ckpGlobalInitArgs = (CK_C_INITIALIZE_ARGS_PTR) malloc(sizeof(CK_C_INITIALIZE_ARGS)); |
156 | if (ckpGlobalInitArgs == NULL) { |
157 | free(ckpInitArgs); |
158 | throwOutOfMemoryError(env, 0); |
159 | return NULL_PTR; |
160 | } |
161 | |
162 | memcpy(ckpGlobalInitArgs, ckpInitArgs, sizeof(CK_C_INITIALIZE_ARGS)); |
163 | } |
164 | #endif /* NO_CALLBACKS */ |
165 | |
166 | /* convert and set the flags field */ |
167 | fieldID = (*env)->GetFieldID(env, jInitArgsClass, "flags" , "J" ); |
168 | if (fieldID == NULL) { |
169 | free(ckpInitArgs); |
170 | return NULL; |
171 | } |
172 | jFlags = (*env)->GetLongField(env, jInitArgs, fieldID); |
173 | ckpInitArgs->flags = jLongToCKULong(jFlags); |
174 | |
175 | /* pReserved should be NULL_PTR in this version */ |
176 | fieldID = (*env)->GetFieldID(env, jInitArgsClass, "pReserved" , "Ljava/lang/Object;" ); |
177 | if (fieldID == NULL) { |
178 | free(ckpInitArgs); |
179 | return NULL; |
180 | } |
181 | jReserved = (*env)->GetObjectField(env, jInitArgs, fieldID); |
182 | |
183 | /* we try to convert the reserved parameter also */ |
184 | ckpInitArgs->pReserved = jObjectToPrimitiveCKObjectPtr(env, jReserved, &ckReservedLength); |
185 | |
186 | return ckpInitArgs ; |
187 | } |
188 | |
189 | #ifndef NO_CALLBACKS |
190 | |
191 | /* |
192 | * is the function that gets called by PKCS#11 to create a mutex and calls the Java |
193 | * CreateMutex function |
194 | * |
195 | * @param env - used to call JNI funktions to get the Java classes, objects, methods and fields |
196 | * @param ppMutex - the new created mutex |
197 | * @return - should return CKR_OK if the mutex creation was ok |
198 | */ |
199 | CK_RV callJCreateMutex(CK_VOID_PTR_PTR ppMutex) |
200 | { |
201 | extern JavaVM *jvm; |
202 | JNIEnv *env; |
203 | jint returnValue; |
204 | jthrowable pkcs11Exception; |
205 | jclass pkcs11ExceptionClass; |
206 | jlong errorCode; |
207 | CK_RV rv = CKR_OK; |
208 | int wasAttached = 1; |
209 | jclass jCreateMutexClass; |
210 | jclass jInitArgsClass; |
211 | jmethodID methodID; |
212 | jfieldID fieldID; |
213 | jobject jCreateMutex; |
214 | jobject jMutex; |
215 | |
216 | |
217 | /* Get the currently running Java VM */ |
218 | if (jvm == NULL) { return rv ;} /* there is no VM running */ |
219 | |
220 | /* Determine, if current thread is already attached */ |
221 | returnValue = (*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION_1_2); |
222 | if (returnValue == JNI_EDETACHED) { |
223 | /* thread detached, so attach it */ |
224 | wasAttached = 0; |
225 | returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL); |
226 | } else if (returnValue == JNI_EVERSION) { |
227 | /* this version of JNI is not supported, so just try to attach */ |
228 | /* we assume it was attached to ensure that this thread is not detached |
229 | * afterwards even though it should not |
230 | */ |
231 | wasAttached = 1; |
232 | returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL); |
233 | } else { |
234 | /* attached */ |
235 | wasAttached = 1; |
236 | } |
237 | |
238 | jCreateMutexClass = (*env)->FindClass(env, CLASS_CREATEMUTEX); |
239 | if (jCreateMutexClass == NULL) { return rv; } |
240 | jInitArgsClass = (*env)->FindClass(env, CLASS_C_INITIALIZE_ARGS); |
241 | if (jInitArgsClass == NULL) { return rv; } |
242 | |
243 | /* get the CreateMutex object out of the jInitArgs object */ |
244 | fieldID = (*env)->GetFieldID(env, jInitArgsClass, "CreateMutex" , "Lsun/security/pkcs11/wrapper/CK_CREATEMUTEX;" ); |
245 | if (fieldID == NULL) { return rv; } |
246 | jCreateMutex = (*env)->GetObjectField(env, jInitArgsObject, fieldID); |
247 | assert(jCreateMutex != 0); |
248 | |
249 | /* call the CK_CREATEMUTEX function of the CreateMutex object */ |
250 | /* and get the new Java mutex object */ |
251 | methodID = (*env)->GetMethodID(env, jCreateMutexClass, "CK_CREATEMUTEX" , "()Ljava/lang/Object;" ); |
252 | if (methodID == NULL) { return rv; } |
253 | jMutex = (*env)->CallObjectMethod(env, jCreateMutex, methodID); |
254 | |
255 | /* set a global reference on the Java mutex */ |
256 | jMutex = (*env)->NewGlobalRef(env, jMutex); |
257 | /* convert the Java mutex to a CK mutex */ |
258 | *ppMutex = jObjectToCKVoidPtr(jMutex); |
259 | |
260 | |
261 | /* check, if callback threw an exception */ |
262 | pkcs11Exception = (*env)->ExceptionOccurred(env); |
263 | |
264 | if (pkcs11Exception != NULL) { |
265 | /* TBD: clear the pending exception with ExceptionClear? */ |
266 | /* The was an exception thrown, now we get the error-code from it */ |
267 | pkcs11ExceptionClass = (*env)->FindClass(env, CLASS_PKCS11EXCEPTION); |
268 | if (pkcs11ExceptionClass == NULL) { return rv; } |
269 | methodID = (*env)->GetMethodID(env, pkcs11ExceptionClass, "getErrorCode" , "()J" ); |
270 | if (methodID == NULL) { return rv; } |
271 | |
272 | errorCode = (*env)->CallLongMethod(env, pkcs11Exception, methodID); |
273 | rv = jLongToCKULong(errorCode); |
274 | } |
275 | |
276 | /* if we attached this thread to the VM just for callback, we detach it now */ |
277 | if (wasAttached) { |
278 | returnValue = (*jvm)->DetachCurrentThread(jvm); |
279 | } |
280 | |
281 | return rv ; |
282 | } |
283 | |
284 | /* |
285 | * is the function that gets called by PKCS#11 to destroy a mutex and calls the Java |
286 | * DestroyMutex function |
287 | * |
288 | * @param env - used to call JNI funktions to get the Java classes, objects, methods and fields |
289 | * @param pMutex - the mutex to destroy |
290 | * @return - should return CKR_OK if the mutex was destroyed |
291 | */ |
292 | CK_RV callJDestroyMutex(CK_VOID_PTR pMutex) |
293 | { |
294 | extern JavaVM *jvm; |
295 | JNIEnv *env; |
296 | jint returnValue; |
297 | jthrowable pkcs11Exception; |
298 | jclass pkcs11ExceptionClass; |
299 | jlong errorCode; |
300 | CK_RV rv = CKR_OK; |
301 | int wasAttached = 1; |
302 | jclass jDestroyMutexClass; |
303 | jclass jInitArgsClass; |
304 | jmethodID methodID; |
305 | jfieldID fieldID; |
306 | jobject jDestroyMutex; |
307 | jobject jMutex; |
308 | |
309 | |
310 | /* Get the currently running Java VM */ |
311 | if (jvm == NULL) { return rv ; } /* there is no VM running */ |
312 | |
313 | /* Determine, if current thread is already attached */ |
314 | returnValue = (*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION_1_2); |
315 | if (returnValue == JNI_EDETACHED) { |
316 | /* thread detached, so attach it */ |
317 | wasAttached = 0; |
318 | returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL); |
319 | } else if (returnValue == JNI_EVERSION) { |
320 | /* this version of JNI is not supported, so just try to attach */ |
321 | /* we assume it was attached to ensure that this thread is not detached |
322 | * afterwards even though it should not |
323 | */ |
324 | wasAttached = 1; |
325 | returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL); |
326 | } else { |
327 | /* attached */ |
328 | wasAttached = 1; |
329 | } |
330 | |
331 | jDestroyMutexClass = (*env)->FindClass(env, CLASS_DESTROYMUTEX); |
332 | if (jDestroyMutexClass == NULL) { return rv; } |
333 | jInitArgsClass = (*env)->FindClass(env, CLASS_C_INITIALIZE_ARGS); |
334 | if (jInitArgsClass == NULL) { return rv; } |
335 | |
336 | /* convert the CK mutex to a Java mutex */ |
337 | jMutex = ckVoidPtrToJObject(pMutex); |
338 | |
339 | /* get the DestroyMutex object out of the jInitArgs object */ |
340 | fieldID = (*env)->GetFieldID(env, jInitArgsClass, "DestroyMutex" , "Lsun/security/pkcs11/wrapper/CK_DESTROYMUTEX;" ); |
341 | if (fieldID == NULL) { return rv; } |
342 | jDestroyMutex = (*env)->GetObjectField(env, jInitArgsObject, fieldID); |
343 | assert(jDestroyMutex != 0); |
344 | |
345 | /* call the CK_DESTROYMUTEX method of the DestroyMutex object */ |
346 | methodID = (*env)->GetMethodID(env, jDestroyMutexClass, "CK_DESTROYMUTEX" , "(Ljava/lang/Object;)V" ); |
347 | if (methodID == NULL) { return rv; } |
348 | (*env)->CallVoidMethod(env, jDestroyMutex, methodID, jMutex); |
349 | |
350 | /* delete the global reference on the Java mutex */ |
351 | (*env)->DeleteGlobalRef(env, jMutex); |
352 | |
353 | |
354 | /* check, if callback threw an exception */ |
355 | pkcs11Exception = (*env)->ExceptionOccurred(env); |
356 | |
357 | if (pkcs11Exception != NULL) { |
358 | /* TBD: clear the pending exception with ExceptionClear? */ |
359 | /* The was an exception thrown, now we get the error-code from it */ |
360 | pkcs11ExceptionClass = (*env)->FindClass(env, CLASS_PKCS11EXCEPTION); |
361 | if (pkcs11ExceptionClass == NULL) { return rv; } |
362 | methodID = (*env)->GetMethodID(env, pkcs11ExceptionClass, "getErrorCode" , "()J" ); |
363 | if (methodID == NULL) { return rv; } |
364 | errorCode = (*env)->CallLongMethod(env, pkcs11Exception, methodID); |
365 | rv = jLongToCKULong(errorCode); |
366 | } |
367 | |
368 | /* if we attached this thread to the VM just for callback, we detach it now */ |
369 | if (wasAttached) { |
370 | returnValue = (*jvm)->DetachCurrentThread(jvm); |
371 | } |
372 | |
373 | return rv ; |
374 | } |
375 | |
376 | /* |
377 | * is the function that gets called by PKCS#11 to lock a mutex and calls the Java |
378 | * LockMutex function |
379 | * |
380 | * @param env - used to call JNI funktions to get the Java classes, objects, methods and fields |
381 | * @param pMutex - the mutex to lock |
382 | * @return - should return CKR_OK if the mutex was not locked already |
383 | */ |
384 | CK_RV callJLockMutex(CK_VOID_PTR pMutex) |
385 | { |
386 | extern JavaVM *jvm; |
387 | JNIEnv *env; |
388 | jint returnValue; |
389 | jthrowable pkcs11Exception; |
390 | jclass pkcs11ExceptionClass; |
391 | jlong errorCode; |
392 | CK_RV rv = CKR_OK; |
393 | int wasAttached = 1; |
394 | jclass jLockMutexClass; |
395 | jclass jInitArgsClass; |
396 | jmethodID methodID; |
397 | jfieldID fieldID; |
398 | jobject jLockMutex; |
399 | jobject jMutex; |
400 | |
401 | |
402 | /* Get the currently running Java VM */ |
403 | if (jvm == NULL) { return rv ; } /* there is no VM running */ |
404 | |
405 | /* Determine, if current thread is already attached */ |
406 | returnValue = (*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION_1_2); |
407 | if (returnValue == JNI_EDETACHED) { |
408 | /* thread detached, so attach it */ |
409 | wasAttached = 0; |
410 | returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL); |
411 | } else if (returnValue == JNI_EVERSION) { |
412 | /* this version of JNI is not supported, so just try to attach */ |
413 | /* we assume it was attached to ensure that this thread is not detached |
414 | * afterwards even though it should not |
415 | */ |
416 | wasAttached = 1; |
417 | returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL); |
418 | } else { |
419 | /* attached */ |
420 | wasAttached = 1; |
421 | } |
422 | |
423 | jLockMutexClass = (*env)->FindClass(env, CLASS_LOCKMUTEX); |
424 | if (jLockMutexClass == NULL) { return rv; } |
425 | jInitArgsClass = (*env)->FindClass(env, CLASS_C_INITIALIZE_ARGS); |
426 | if (jInitArgsClass == NULL) { return rv; } |
427 | |
428 | /* convert the CK mutex to a Java mutex */ |
429 | jMutex = ckVoidPtrToJObject(pMutex); |
430 | |
431 | /* get the LockMutex object out of the jInitArgs object */ |
432 | fieldID = (*env)->GetFieldID(env, jInitArgsClass, "LockMutex" , "Lsun/security/pkcs11/wrapper/CK_LOCKMUTEX;" ); |
433 | if (fieldID == NULL) { return rv; } |
434 | jLockMutex = (*env)->GetObjectField(env, jInitArgsObject, fieldID); |
435 | assert(jLockMutex != 0); |
436 | |
437 | /* call the CK_LOCKMUTEX method of the LockMutex object */ |
438 | methodID = (*env)->GetMethodID(env, jLockMutexClass, "CK_LOCKMUTEX" , "(Ljava/lang/Object;)V" ); |
439 | if (methodID == NULL) { return rv; } |
440 | (*env)->CallVoidMethod(env, jLockMutex, methodID, jMutex); |
441 | |
442 | /* check, if callback threw an exception */ |
443 | pkcs11Exception = (*env)->ExceptionOccurred(env); |
444 | |
445 | if (pkcs11Exception != NULL) { |
446 | /* TBD: clear the pending exception with ExceptionClear? */ |
447 | /* The was an exception thrown, now we get the error-code from it */ |
448 | pkcs11ExceptionClass = (*env)->FindClass(env, CLASS_PKCS11EXCEPTION); |
449 | if (pkcs11ExceptionClass == NULL) { return rv; } |
450 | methodID = (*env)->GetMethodID(env, pkcs11ExceptionClass, "getErrorCode" , "()J" ); |
451 | if (methodID == NULL) { return rv; } |
452 | errorCode = (*env)->CallLongMethod(env, pkcs11Exception, methodID); |
453 | rv = jLongToCKULong(errorCode); |
454 | } |
455 | |
456 | /* if we attached this thread to the VM just for callback, we detach it now */ |
457 | if (wasAttached) { |
458 | returnValue = (*jvm)->DetachCurrentThread(jvm); |
459 | } |
460 | |
461 | return rv ; |
462 | } |
463 | |
464 | /* |
465 | * is the function that gets called by PKCS#11 to unlock a mutex and calls the Java |
466 | * UnlockMutex function |
467 | * |
468 | * @param env - used to call JNI funktions to get the Java classes, objects, methods and fields |
469 | * @param pMutex - the mutex to unlock |
470 | * @return - should return CKR_OK if the mutex was not unlocked already |
471 | */ |
472 | CK_RV callJUnlockMutex(CK_VOID_PTR pMutex) |
473 | { |
474 | extern JavaVM *jvm; |
475 | JNIEnv *env; |
476 | jint returnValue; |
477 | jthrowable pkcs11Exception; |
478 | jclass pkcs11ExceptionClass; |
479 | jlong errorCode; |
480 | CK_RV rv = CKR_OK; |
481 | int wasAttached = 1; |
482 | jclass jUnlockMutexClass; |
483 | jclass jInitArgsClass; |
484 | jmethodID methodID; |
485 | jfieldID fieldID; |
486 | jobject jUnlockMutex; |
487 | jobject jMutex; |
488 | |
489 | |
490 | /* Get the currently running Java VM */ |
491 | if (jvm == NULL) { return rv ; } /* there is no VM running */ |
492 | |
493 | /* Determine, if current thread is already attached */ |
494 | returnValue = (*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION_1_2); |
495 | if (returnValue == JNI_EDETACHED) { |
496 | /* thread detached, so attach it */ |
497 | wasAttached = 0; |
498 | returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL); |
499 | } else if (returnValue == JNI_EVERSION) { |
500 | /* this version of JNI is not supported, so just try to attach */ |
501 | /* we assume it was attached to ensure that this thread is not detached |
502 | * afterwards even though it should not |
503 | */ |
504 | wasAttached = 1; |
505 | returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL); |
506 | } else { |
507 | /* attached */ |
508 | wasAttached = 1; |
509 | } |
510 | |
511 | jUnlockMutexClass = (*env)->FindClass(env, CLASS_UNLOCKMUTEX); |
512 | if (jUnlockMutexClass == NULL) { return rv; } |
513 | jInitArgsClass = (*env)->FindClass(env, CLASS_C_INITIALIZE_ARGS); |
514 | if (jInitArgsClass == NULL) { return rv; } |
515 | |
516 | /* convert the CK-type mutex to a Java mutex */ |
517 | jMutex = ckVoidPtrToJObject(pMutex); |
518 | |
519 | /* get the UnlockMutex object out of the jInitArgs object */ |
520 | fieldID = (*env)->GetFieldID(env, jInitArgsClass, "UnlockMutex" , "Lsun/security/pkcs11/wrapper/CK_UNLOCKMUTEX;" ); |
521 | if (fieldID == NULL) { return rv; } |
522 | jUnlockMutex = (*env)->GetObjectField(env, jInitArgsObject, fieldID); |
523 | assert(jUnlockMutex != 0); |
524 | |
525 | /* call the CK_UNLOCKMUTEX method of the UnLockMutex object */ |
526 | methodID = (*env)->GetMethodID(env, jUnlockMutexClass, "CK_UNLOCKMUTEX" , "(Ljava/lang/Object;)V" ); |
527 | if (methodID == NULL) { return rv; } |
528 | (*env)->CallVoidMethod(env, jUnlockMutex, methodID, jMutex); |
529 | |
530 | /* check, if callback threw an exception */ |
531 | pkcs11Exception = (*env)->ExceptionOccurred(env); |
532 | |
533 | if (pkcs11Exception != NULL) { |
534 | /* TBD: clear the pending exception with ExceptionClear? */ |
535 | /* The was an exception thrown, now we get the error-code from it */ |
536 | pkcs11ExceptionClass = (*env)->FindClass(env, CLASS_PKCS11EXCEPTION); |
537 | if (pkcs11ExceptionClass == NULL) { return rv; } |
538 | methodID = (*env)->GetMethodID(env, pkcs11ExceptionClass, "getErrorCode" , "()J" ); |
539 | if (methodID == NULL) { return rv; } |
540 | errorCode = (*env)->CallLongMethod(env, pkcs11Exception, methodID); |
541 | rv = jLongToCKULong(errorCode); |
542 | } |
543 | |
544 | /* if we attached this thread to the VM just for callback, we detach it now */ |
545 | if (wasAttached) { |
546 | returnValue = (*jvm)->DetachCurrentThread(jvm); |
547 | } |
548 | |
549 | return rv ; |
550 | } |
551 | |
552 | #endif /* NO_CALLBACKS */ |
553 | |