jdk/src/jdk.crypto.token/share/native/libj2pkcs11/p11_mutex.c
changeset 42693 6645de32a866
parent 42455 a66ed8458668
equal deleted inserted replaced
42692:97247477b481 42693:6645de32a866
       
     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 */