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