0N/A/*
2362N/A * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
0N/A */
0N/A
0N/A/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
0N/A *
0N/A * Redistribution and use in source and binary forms, with or without
0N/A * modification, are permitted provided that the following conditions are met:
0N/A *
0N/A * 1. Redistributions of source code must retain the above copyright notice,
0N/A * this list of conditions and the following disclaimer.
0N/A *
0N/A * 2. Redistributions in binary form must reproduce the above copyright notice,
0N/A * this list of conditions and the following disclaimer in the documentation
0N/A * and/or other materials provided with the distribution.
0N/A *
0N/A * 3. The end-user documentation included with the redistribution, if any, must
0N/A * include the following acknowledgment:
0N/A *
0N/A * "This product includes software developed by IAIK of Graz University of
0N/A * Technology."
0N/A *
0N/A * Alternately, this acknowledgment may appear in the software itself, if
0N/A * and wherever such third-party acknowledgments normally appear.
0N/A *
0N/A * 4. The names "Graz University of Technology" and "IAIK of Graz University of
0N/A * Technology" must not be used to endorse or promote products derived from
0N/A * this software without prior written permission.
0N/A *
0N/A * 5. Products derived from this software may not be called
0N/A * "IAIK PKCS Wrapper", nor may "IAIK" appear in their name, without prior
0N/A * written permission of Graz University of Technology.
0N/A *
0N/A * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
0N/A * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
0N/A * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
0N/A * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
0N/A * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
0N/A * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
0N/A * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
0N/A * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
0N/A * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
0N/A * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
0N/A * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0N/A * POSSIBILITY OF SUCH DAMAGE.
0N/A */
0N/A
0N/A#include "pkcs11wrapper.h"
0N/A
0N/A#include <stdio.h>
0N/A#include <stdlib.h>
0N/A#include <string.h>
0N/A#include <assert.h>
0N/A
0N/A#include "sun_security_pkcs11_wrapper_PKCS11.h"
0N/A
0N/A/* The initArgs that enable the application to do custom mutex-handling */
0N/A#ifndef NO_CALLBACKS
0N/Ajobject jInitArgsObject;
0N/ACK_C_INITIALIZE_ARGS_PTR ckpGlobalInitArgs;
0N/A#endif /* NO_CALLBACKS */
0N/A
0N/A/* ************************************************************************** */
0N/A/* Now come the functions for mutex handling and notification callbacks */
0N/A/* ************************************************************************** */
0N/A
0N/A/*
0N/A * converts the InitArgs object to a CK_C_INITIALIZE_ARGS structure and sets the functions
0N/A * that will call the right Java mutex functions
0N/A *
0N/A * @param env - used to call JNI funktions to get the Java classes, objects, methods and fields
0N/A * @param pInitArgs - the InitArgs object with the Java mutex functions to call
0N/A * @return - the pointer to the CK_C_INITIALIZE_ARGS structure with the functions that will call
0N/A * the corresponding Java functions
0N/A */
0N/ACK_C_INITIALIZE_ARGS_PTR makeCKInitArgsAdapter(JNIEnv *env, jobject jInitArgs)
0N/A{
0N/A CK_C_INITIALIZE_ARGS_PTR ckpInitArgs;
936N/A jclass jInitArgsClass;
0N/A jfieldID fieldID;
0N/A jlong jFlags;
0N/A jobject jReserved;
0N/A CK_ULONG ckReservedLength;
0N/A#ifndef NO_CALLBACKS
0N/A jobject jMutexHandler;
0N/A#endif /* NO_CALLBACKS */
0N/A
0N/A if(jInitArgs == NULL) {
0N/A return NULL_PTR;
0N/A }
0N/A
0N/A /* convert the Java InitArgs object to a pointer to a CK_C_INITIALIZE_ARGS structure */
0N/A ckpInitArgs = (CK_C_INITIALIZE_ARGS_PTR) malloc(sizeof(CK_C_INITIALIZE_ARGS));
936N/A if (ckpInitArgs == NULL) {
936N/A JNU_ThrowOutOfMemoryError(env, 0);
936N/A return NULL_PTR;
936N/A }
0N/A
0N/A /* Set the mutex functions that will call the Java mutex functions, but
0N/A * only set it, if the field is not null.
0N/A */
936N/A jInitArgsClass = (*env)->FindClass(env, CLASS_C_INITIALIZE_ARGS);
936N/A if (jInitArgsClass == NULL) {
936N/A free(ckpInitArgs);
936N/A return NULL;
936N/A }
936N/A
0N/A#ifdef NO_CALLBACKS
0N/A ckpInitArgs->CreateMutex = NULL_PTR;
0N/A ckpInitArgs->DestroyMutex = NULL_PTR;
0N/A ckpInitArgs->LockMutex = NULL_PTR;
0N/A ckpInitArgs->UnlockMutex = NULL_PTR;
0N/A#else
0N/A fieldID = (*env)->GetFieldID(env, jInitArgsClass, "CreateMutex", "Lsun/security/pkcs11/wrapper/CK_CREATEMUTEX;");
936N/A if (fieldID == NULL) { return NULL; }
0N/A jMutexHandler = (*env)->GetObjectField(env, jInitArgs, fieldID);
0N/A ckpInitArgs->CreateMutex = (jMutexHandler != NULL) ? &callJCreateMutex : NULL_PTR;
0N/A
0N/A fieldID = (*env)->GetFieldID(env, jInitArgsClass, "DestroyMutex", "Lsun/security/pkcs11/wrapper/CK_DESTROYMUTEX;");
936N/A if (fieldID == NULL) { return NULL; }
0N/A jMutexHandler = (*env)->GetObjectField(env, jInitArgs, fieldID);
0N/A ckpInitArgs->DestroyMutex = (jMutexHandler != NULL) ? &callJDestroyMutex : NULL_PTR;
0N/A
0N/A fieldID = (*env)->GetFieldID(env, jInitArgsClass, "LockMutex", "Lsun/security/pkcs11/wrapper/CK_LOCKMUTEX;");
936N/A if (fieldID == NULL) { return NULL; }
0N/A jMutexHandler = (*env)->GetObjectField(env, jInitArgs, fieldID);
0N/A ckpInitArgs->LockMutex = (jMutexHandler != NULL) ? &callJLockMutex : NULL_PTR;
0N/A
0N/A fieldID = (*env)->GetFieldID(env, jInitArgsClass, "UnlockMutex", "Lsun/security/pkcs11/wrapper/CK_UNLOCKMUTEX;");
936N/A if (fieldID == NULL) { return NULL; }
0N/A jMutexHandler = (*env)->GetObjectField(env, jInitArgs, fieldID);
0N/A ckpInitArgs->UnlockMutex = (jMutexHandler != NULL) ? &callJUnlockMutex : NULL_PTR;
0N/A
0N/A if ((ckpInitArgs->CreateMutex != NULL_PTR)
0N/A || (ckpInitArgs->DestroyMutex != NULL_PTR)
0N/A || (ckpInitArgs->LockMutex != NULL_PTR)
0N/A || (ckpInitArgs->UnlockMutex != NULL_PTR)) {
0N/A /* we only need to keep a global copy, if we need callbacks */
0N/A /* set the global object jInitArgs so that the right Java mutex functions will be called */
0N/A jInitArgsObject = (*env)->NewGlobalRef(env, jInitArgs);
0N/A ckpGlobalInitArgs = (CK_C_INITIALIZE_ARGS_PTR) malloc(sizeof(CK_C_INITIALIZE_ARGS));
936N/A if (ckpGlobalInitArgs == NULL) {
936N/A free(ckpInitArgs);
936N/A JNU_ThrowOutOfMemoryError(env, 0);
936N/A return NULL_PTR;
936N/A }
936N/A
0N/A memcpy(ckpGlobalInitArgs, ckpInitArgs, sizeof(CK_C_INITIALIZE_ARGS));
0N/A }
0N/A#endif /* NO_CALLBACKS */
0N/A
0N/A /* convert and set the flags field */
0N/A fieldID = (*env)->GetFieldID(env, jInitArgsClass, "flags", "J");
936N/A if (fieldID == NULL) { return NULL; }
0N/A jFlags = (*env)->GetLongField(env, jInitArgs, fieldID);
0N/A ckpInitArgs->flags = jLongToCKULong(jFlags);
0N/A
0N/A /* pReserved should be NULL_PTR in this version */
0N/A fieldID = (*env)->GetFieldID(env, jInitArgsClass, "pReserved", "Ljava/lang/Object;");
936N/A if (fieldID == NULL) { return NULL; }
0N/A jReserved = (*env)->GetObjectField(env, jInitArgs, fieldID);
0N/A
0N/A /* we try to convert the reserved parameter also */
0N/A jObjectToPrimitiveCKObjectPtrPtr(env, jReserved, &(ckpInitArgs->pReserved), &ckReservedLength);
0N/A
0N/A return ckpInitArgs ;
0N/A}
0N/A
0N/A#ifndef NO_CALLBACKS
0N/A
0N/A/*
0N/A * is the function that gets called by PKCS#11 to create a mutex and calls the Java
0N/A * CreateMutex function
0N/A *
0N/A * @param env - used to call JNI funktions to get the Java classes, objects, methods and fields
0N/A * @param ppMutex - the new created mutex
0N/A * @return - should return CKR_OK if the mutex creation was ok
0N/A */
0N/ACK_RV callJCreateMutex(CK_VOID_PTR_PTR ppMutex)
0N/A{
0N/A JavaVM *jvm;
0N/A JNIEnv *env;
0N/A jsize actualNumberVMs;
0N/A jint returnValue;
0N/A jthrowable pkcs11Exception;
0N/A jclass pkcs11ExceptionClass;
0N/A jlong errorCode;
0N/A CK_RV rv = CKR_OK;
0N/A int wasAttached = 1;
0N/A jclass jCreateMutexClass;
0N/A jclass jInitArgsClass;
0N/A jmethodID methodID;
0N/A jfieldID fieldID;
0N/A jobject jCreateMutex;
0N/A jobject jMutex;
0N/A
0N/A
0N/A /* Get the currently running Java VM */
0N/A returnValue = JNI_GetCreatedJavaVMs(&jvm, (jsize) 1, &actualNumberVMs);
0N/A if ((returnValue != 0) || (actualNumberVMs <= 0)) { return rv ;} /* there is no VM running */
0N/A
0N/A /* Determine, if current thread is already attached */
0N/A returnValue = (*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION_1_2);
0N/A if (returnValue == JNI_EDETACHED) {
0N/A /* thread detached, so attach it */
0N/A wasAttached = 0;
0N/A returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL);
0N/A } else if (returnValue == JNI_EVERSION) {
0N/A /* this version of JNI is not supported, so just try to attach */
0N/A /* we assume it was attached to ensure that this thread is not detached
0N/A * afterwards even though it should not
0N/A */
0N/A wasAttached = 1;
0N/A returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL);
0N/A } else {
0N/A /* attached */
0N/A wasAttached = 1;
0N/A }
0N/A
0N/A jCreateMutexClass = (*env)->FindClass(env, CLASS_CREATEMUTEX);
936N/A if (jCreateMutexClass == NULL) { return rv; }
0N/A jInitArgsClass = (*env)->FindClass(env, CLASS_C_INITIALIZE_ARGS);
936N/A if (jInitArgsClass == NULL) { return rv; }
0N/A
0N/A /* get the CreateMutex object out of the jInitArgs object */
0N/A fieldID = (*env)->GetFieldID(env, jInitArgsClass, "CreateMutex", "Lsun/security/pkcs11/wrapper/CK_CREATEMUTEX;");
936N/A if (fieldID == NULL) { return rv; }
0N/A jCreateMutex = (*env)->GetObjectField(env, jInitArgsObject, fieldID);
0N/A assert(jCreateMutex != 0);
0N/A
0N/A /* call the CK_CREATEMUTEX function of the CreateMutex object */
0N/A /* and get the new Java mutex object */
0N/A methodID = (*env)->GetMethodID(env, jCreateMutexClass, "CK_CREATEMUTEX", "()Ljava/lang/Object;");
936N/A if (methodID == NULL) { return rv; }
0N/A jMutex = (*env)->CallObjectMethod(env, jCreateMutex, methodID);
0N/A
0N/A /* set a global reference on the Java mutex */
0N/A jMutex = (*env)->NewGlobalRef(env, jMutex);
0N/A /* convert the Java mutex to a CK mutex */
0N/A *ppMutex = jObjectToCKVoidPtr(jMutex);
0N/A
0N/A
0N/A /* check, if callback threw an exception */
0N/A pkcs11Exception = (*env)->ExceptionOccurred(env);
0N/A
0N/A if (pkcs11Exception != NULL) {
936N/A /* TBD: clear the pending exception with ExceptionClear? */
0N/A /* The was an exception thrown, now we get the error-code from it */
0N/A pkcs11ExceptionClass = (*env)->FindClass(env, CLASS_PKCS11EXCEPTION);
936N/A if (pkcs11ExceptionClass == NULL) { return rv; }
0N/A methodID = (*env)->GetMethodID(env, pkcs11ExceptionClass, "getErrorCode", "()J");
936N/A if (methodID == NULL) { return rv; }
936N/A
0N/A errorCode = (*env)->CallLongMethod(env, pkcs11Exception, methodID);
0N/A rv = jLongToCKULong(errorCode);
0N/A }
0N/A
0N/A /* if we attached this thread to the VM just for callback, we detach it now */
0N/A if (wasAttached) {
0N/A returnValue = (*jvm)->DetachCurrentThread(jvm);
0N/A }
0N/A
0N/A return rv ;
0N/A}
0N/A
0N/A/*
0N/A * is the function that gets called by PKCS#11 to destroy a mutex and calls the Java
0N/A * DestroyMutex function
0N/A *
0N/A * @param env - used to call JNI funktions to get the Java classes, objects, methods and fields
0N/A * @param pMutex - the mutex to destroy
0N/A * @return - should return CKR_OK if the mutex was destroyed
0N/A */
0N/ACK_RV callJDestroyMutex(CK_VOID_PTR pMutex)
0N/A{
0N/A JavaVM *jvm;
0N/A JNIEnv *env;
0N/A jsize actualNumberVMs;
0N/A jint returnValue;
0N/A jthrowable pkcs11Exception;
0N/A jclass pkcs11ExceptionClass;
0N/A jlong errorCode;
0N/A CK_RV rv = CKR_OK;
0N/A int wasAttached = 1;
0N/A jclass jDestroyMutexClass;
0N/A jclass jInitArgsClass;
0N/A jmethodID methodID;
0N/A jfieldID fieldID;
0N/A jobject jDestroyMutex;
0N/A jobject jMutex;
0N/A
0N/A
0N/A /* Get the currently running Java VM */
0N/A returnValue = JNI_GetCreatedJavaVMs(&jvm, (jsize) 1, &actualNumberVMs);
0N/A if ((returnValue != 0) || (actualNumberVMs <= 0)) { return rv ; } /* there is no VM running */
0N/A
0N/A /* Determine, if current thread is already attached */
0N/A returnValue = (*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION_1_2);
0N/A if (returnValue == JNI_EDETACHED) {
0N/A /* thread detached, so attach it */
0N/A wasAttached = 0;
0N/A returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL);
0N/A } else if (returnValue == JNI_EVERSION) {
0N/A /* this version of JNI is not supported, so just try to attach */
0N/A /* we assume it was attached to ensure that this thread is not detached
0N/A * afterwards even though it should not
0N/A */
0N/A wasAttached = 1;
0N/A returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL);
0N/A } else {
0N/A /* attached */
0N/A wasAttached = 1;
0N/A }
0N/A
0N/A jDestroyMutexClass = (*env)->FindClass(env, CLASS_DESTROYMUTEX);
936N/A if (jDestroyMutexClass == NULL) { return rv; }
0N/A jInitArgsClass = (*env)->FindClass(env, CLASS_C_INITIALIZE_ARGS);
936N/A if (jInitArgsClass == NULL) { return rv; }
0N/A
0N/A /* convert the CK mutex to a Java mutex */
0N/A jMutex = ckVoidPtrToJObject(pMutex);
0N/A
0N/A /* get the DestroyMutex object out of the jInitArgs object */
0N/A fieldID = (*env)->GetFieldID(env, jInitArgsClass, "DestroyMutex", "Lsun/security/pkcs11/wrapper/CK_DESTROYMUTEX;");
936N/A if (fieldID == NULL) { return rv; }
0N/A jDestroyMutex = (*env)->GetObjectField(env, jInitArgsObject, fieldID);
0N/A assert(jDestroyMutex != 0);
0N/A
0N/A /* call the CK_DESTROYMUTEX method of the DestroyMutex object */
0N/A methodID = (*env)->GetMethodID(env, jDestroyMutexClass, "CK_DESTROYMUTEX", "(Ljava/lang/Object;)V");
936N/A if (methodID == NULL) { return rv; }
0N/A (*env)->CallVoidMethod(env, jDestroyMutex, methodID, jMutex);
0N/A
0N/A /* delete the global reference on the Java mutex */
0N/A (*env)->DeleteGlobalRef(env, jMutex);
0N/A
0N/A
0N/A /* check, if callback threw an exception */
0N/A pkcs11Exception = (*env)->ExceptionOccurred(env);
0N/A
0N/A if (pkcs11Exception != NULL) {
936N/A /* TBD: clear the pending exception with ExceptionClear? */
0N/A /* The was an exception thrown, now we get the error-code from it */
0N/A pkcs11ExceptionClass = (*env)->FindClass(env, CLASS_PKCS11EXCEPTION);
936N/A if (pkcs11ExceptionClass == NULL) { return rv; }
0N/A methodID = (*env)->GetMethodID(env, pkcs11ExceptionClass, "getErrorCode", "()J");
936N/A if (methodID == NULL) { return rv; }
0N/A errorCode = (*env)->CallLongMethod(env, pkcs11Exception, methodID);
0N/A rv = jLongToCKULong(errorCode);
0N/A }
0N/A
0N/A /* if we attached this thread to the VM just for callback, we detach it now */
0N/A if (wasAttached) {
0N/A returnValue = (*jvm)->DetachCurrentThread(jvm);
0N/A }
0N/A
0N/A return rv ;
0N/A}
0N/A
0N/A/*
0N/A * is the function that gets called by PKCS#11 to lock a mutex and calls the Java
0N/A * LockMutex function
0N/A *
0N/A * @param env - used to call JNI funktions to get the Java classes, objects, methods and fields
0N/A * @param pMutex - the mutex to lock
0N/A * @return - should return CKR_OK if the mutex was not locked already
0N/A */
0N/ACK_RV callJLockMutex(CK_VOID_PTR pMutex)
0N/A{
0N/A JavaVM *jvm;
0N/A JNIEnv *env;
0N/A jsize actualNumberVMs;
0N/A jint returnValue;
0N/A jthrowable pkcs11Exception;
0N/A jclass pkcs11ExceptionClass;
0N/A jlong errorCode;
0N/A CK_RV rv = CKR_OK;
0N/A int wasAttached = 1;
0N/A jclass jLockMutexClass;
0N/A jclass jInitArgsClass;
0N/A jmethodID methodID;
0N/A jfieldID fieldID;
0N/A jobject jLockMutex;
0N/A jobject jMutex;
0N/A
0N/A
0N/A /* Get the currently running Java VM */
0N/A returnValue = JNI_GetCreatedJavaVMs(&jvm, (jsize) 1, &actualNumberVMs);
0N/A if ((returnValue != 0) || (actualNumberVMs <= 0)) { return rv ; } /* there is no VM running */
0N/A
0N/A /* Determine, if current thread is already attached */
0N/A returnValue = (*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION_1_2);
0N/A if (returnValue == JNI_EDETACHED) {
0N/A /* thread detached, so attach it */
0N/A wasAttached = 0;
0N/A returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL);
0N/A } else if (returnValue == JNI_EVERSION) {
0N/A /* this version of JNI is not supported, so just try to attach */
0N/A /* we assume it was attached to ensure that this thread is not detached
0N/A * afterwards even though it should not
0N/A */
0N/A wasAttached = 1;
0N/A returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL);
0N/A } else {
0N/A /* attached */
0N/A wasAttached = 1;
0N/A }
0N/A
0N/A jLockMutexClass = (*env)->FindClass(env, CLASS_LOCKMUTEX);
936N/A if (jLockMutexClass == NULL) { return rv; }
0N/A jInitArgsClass = (*env)->FindClass(env, CLASS_C_INITIALIZE_ARGS);
936N/A if (jInitArgsClass == NULL) { return rv; }
0N/A
0N/A /* convert the CK mutex to a Java mutex */
0N/A jMutex = ckVoidPtrToJObject(pMutex);
0N/A
0N/A /* get the LockMutex object out of the jInitArgs object */
0N/A fieldID = (*env)->GetFieldID(env, jInitArgsClass, "LockMutex", "Lsun/security/pkcs11/wrapper/CK_LOCKMUTEX;");
936N/A if (fieldID == NULL) { return rv; }
0N/A jLockMutex = (*env)->GetObjectField(env, jInitArgsObject, fieldID);
0N/A assert(jLockMutex != 0);
0N/A
0N/A /* call the CK_LOCKMUTEX method of the LockMutex object */
0N/A methodID = (*env)->GetMethodID(env, jLockMutexClass, "CK_LOCKMUTEX", "(Ljava/lang/Object;)V");
936N/A if (methodID == NULL) { return rv; }
0N/A (*env)->CallVoidMethod(env, jLockMutex, methodID, jMutex);
0N/A
0N/A /* check, if callback threw an exception */
0N/A pkcs11Exception = (*env)->ExceptionOccurred(env);
0N/A
0N/A if (pkcs11Exception != NULL) {
936N/A /* TBD: clear the pending exception with ExceptionClear? */
0N/A /* The was an exception thrown, now we get the error-code from it */
0N/A pkcs11ExceptionClass = (*env)->FindClass(env, CLASS_PKCS11EXCEPTION);
936N/A if (pkcs11ExceptionClass == NULL) { return rv; }
0N/A methodID = (*env)->GetMethodID(env, pkcs11ExceptionClass, "getErrorCode", "()J");
936N/A if (methodID == NULL) { return rv; }
0N/A errorCode = (*env)->CallLongMethod(env, pkcs11Exception, methodID);
0N/A rv = jLongToCKULong(errorCode);
0N/A }
0N/A
0N/A /* if we attached this thread to the VM just for callback, we detach it now */
0N/A if (wasAttached) {
0N/A returnValue = (*jvm)->DetachCurrentThread(jvm);
0N/A }
0N/A
0N/A return rv ;
0N/A}
0N/A
0N/A/*
0N/A * is the function that gets called by PKCS#11 to unlock a mutex and calls the Java
0N/A * UnlockMutex function
0N/A *
0N/A * @param env - used to call JNI funktions to get the Java classes, objects, methods and fields
0N/A * @param pMutex - the mutex to unlock
0N/A * @return - should return CKR_OK if the mutex was not unlocked already
0N/A */
0N/ACK_RV callJUnlockMutex(CK_VOID_PTR pMutex)
0N/A{
0N/A JavaVM *jvm;
0N/A JNIEnv *env;
0N/A jsize actualNumberVMs;
0N/A jint returnValue;
0N/A jthrowable pkcs11Exception;
0N/A jclass pkcs11ExceptionClass;
0N/A jlong errorCode;
0N/A CK_RV rv = CKR_OK;
0N/A int wasAttached = 1;
0N/A jclass jUnlockMutexClass;
0N/A jclass jInitArgsClass;
0N/A jmethodID methodID;
0N/A jfieldID fieldID;
0N/A jobject jUnlockMutex;
0N/A jobject jMutex;
0N/A
0N/A
0N/A /* Get the currently running Java VM */
0N/A returnValue = JNI_GetCreatedJavaVMs(&jvm, (jsize) 1, &actualNumberVMs);
0N/A if ((returnValue != 0) || (actualNumberVMs <= 0)) { return rv ; } /* there is no VM running */
0N/A
0N/A /* Determine, if current thread is already attached */
0N/A returnValue = (*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION_1_2);
0N/A if (returnValue == JNI_EDETACHED) {
0N/A /* thread detached, so attach it */
0N/A wasAttached = 0;
0N/A returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL);
0N/A } else if (returnValue == JNI_EVERSION) {
0N/A /* this version of JNI is not supported, so just try to attach */
0N/A /* we assume it was attached to ensure that this thread is not detached
0N/A * afterwards even though it should not
0N/A */
0N/A wasAttached = 1;
0N/A returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL);
0N/A } else {
0N/A /* attached */
0N/A wasAttached = 1;
0N/A }
0N/A
0N/A jUnlockMutexClass = (*env)->FindClass(env, CLASS_UNLOCKMUTEX);
936N/A if (jUnlockMutexClass == NULL) { return rv; }
0N/A jInitArgsClass = (*env)->FindClass(env, CLASS_C_INITIALIZE_ARGS);
936N/A if (jInitArgsClass == NULL) { return rv; }
0N/A
0N/A /* convert the CK-type mutex to a Java mutex */
0N/A jMutex = ckVoidPtrToJObject(pMutex);
0N/A
0N/A /* get the UnlockMutex object out of the jInitArgs object */
0N/A fieldID = (*env)->GetFieldID(env, jInitArgsClass, "UnlockMutex", "Lsun/security/pkcs11/wrapper/CK_UNLOCKMUTEX;");
936N/A if (fieldID == NULL) { return rv; }
0N/A jUnlockMutex = (*env)->GetObjectField(env, jInitArgsObject, fieldID);
0N/A assert(jUnlockMutex != 0);
0N/A
0N/A /* call the CK_UNLOCKMUTEX method of the UnLockMutex object */
0N/A methodID = (*env)->GetMethodID(env, jUnlockMutexClass, "CK_UNLOCKMUTEX", "(Ljava/lang/Object;)V");
936N/A if (methodID == NULL) { return rv; }
0N/A (*env)->CallVoidMethod(env, jUnlockMutex, methodID, jMutex);
0N/A
0N/A /* check, if callback threw an exception */
0N/A pkcs11Exception = (*env)->ExceptionOccurred(env);
0N/A
0N/A if (pkcs11Exception != NULL) {
936N/A /* TBD: clear the pending exception with ExceptionClear? */
0N/A /* The was an exception thrown, now we get the error-code from it */
0N/A pkcs11ExceptionClass = (*env)->FindClass(env, CLASS_PKCS11EXCEPTION);
936N/A if (pkcs11ExceptionClass == NULL) { return rv; }
0N/A methodID = (*env)->GetMethodID(env, pkcs11ExceptionClass, "getErrorCode", "()J");
936N/A if (methodID == NULL) { return rv; }
0N/A errorCode = (*env)->CallLongMethod(env, pkcs11Exception, methodID);
0N/A rv = jLongToCKULong(errorCode);
0N/A }
0N/A
0N/A /* if we attached this thread to the VM just for callback, we detach it now */
0N/A if (wasAttached) {
0N/A returnValue = (*jvm)->DetachCurrentThread(jvm);
0N/A }
0N/A
0N/A return rv ;
0N/A}
0N/A
0N/A#endif /* NO_CALLBACKS */