1 /* 2 * Copyright (c) 2003, 2016, 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 jObjectToPrimitiveCKObjectPtrPtr(env, jReserved, &(ckpInitArgs->pReserved), &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 */