--- old/src/jdk.crypto.token/share/native/libj2pkcs11/p11_sessmgmt.c 2017-01-20 09:52:58.342288201 -0800 +++ /dev/null 2017-01-18 09:30:05.425422781 -0800 @@ -1,634 +0,0 @@ -/* - * Copyright (c) 2003, 2013, 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 list of notify callback handles that are currently active and waiting - * for callbacks from their sessions. - */ -#ifndef NO_CALLBACKS -NotifyListNode *notifyListHead = NULL; -jobject notifyListLock = NULL; -#endif /* NO_CALLBACKS */ - -#ifdef P11_ENABLE_C_OPENSESSION -/* - * Class: sun_security_pkcs11_wrapper_PKCS11 - * Method: C_OpenSession - * Signature: (JJLjava/lang/Object;Lsun/security/pkcs11/wrapper/CK_NOTIFY;)J - * Parametermapping: *PKCS11* - * @param jlong jSlotID CK_SLOT_ID slotID - * @param jlong jFlags CK_FLAGS flags - * @param jobject jApplication CK_VOID_PTR pApplication - * @param jobject jNotify CK_NOTIFY Notify - * @return jlong jSessionHandle CK_SESSION_HANDLE_PTR phSession - */ -JNIEXPORT jlong JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1OpenSession - (JNIEnv *env, jobject obj, jlong jSlotID, jlong jFlags, jobject jApplication, jobject jNotify) -{ - CK_SESSION_HANDLE ckSessionHandle; - CK_SLOT_ID ckSlotID; - CK_FLAGS ckFlags; - CK_VOID_PTR ckpApplication; - CK_NOTIFY ckNotify; - jlong jSessionHandle; - CK_RV rv; -#ifndef NO_CALLBACKS - NotifyEncapsulation *notifyEncapsulation = NULL; -#endif /* NO_CALLBACKS */ - - CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj); - if (ckpFunctions == NULL) { return 0L; } - - ckSlotID = jLongToCKULong(jSlotID); - ckFlags = jLongToCKULong(jFlags); - -#ifndef NO_CALLBACKS - if (jNotify != NULL) { - notifyEncapsulation = (NotifyEncapsulation *) malloc(sizeof(NotifyEncapsulation)); - if (notifyEncapsulation == NULL) { - throwOutOfMemoryError(env, 0); - return 0L; - } - notifyEncapsulation->jApplicationData = (jApplication != NULL) - ? (*env)->NewGlobalRef(env, jApplication) - : NULL; - notifyEncapsulation->jNotifyObject = (*env)->NewGlobalRef(env, jNotify); - ckpApplication = notifyEncapsulation; - ckNotify = (CK_NOTIFY) ¬ifyCallback; - } else { - ckpApplication = NULL_PTR; - ckNotify = NULL_PTR; - } -#else - ckpApplication = NULL_PTR; - ckNotify = NULL_PTR; -#endif /* NO_CALLBACKS */ - - TRACE0("DEBUG: C_OpenSession"); - TRACE1(", slotID=%u", ckSlotID); - TRACE1(", flags=%x", ckFlags); - TRACE0(" ... "); - - rv = (*ckpFunctions->C_OpenSession)(ckSlotID, ckFlags, ckpApplication, ckNotify, &ckSessionHandle); - if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { -#ifndef NO_CALLBACKS - if (notifyEncapsulation != NULL) { - if (notifyEncapsulation->jApplicationData != NULL) { - (*env)->DeleteGlobalRef(env, jApplication); - } - (*env)->DeleteGlobalRef(env, jNotify); - free(notifyEncapsulation); - } -#endif /* NO_CALLBACKS */ - return 0L; - } - - TRACE0("got session"); - TRACE1(", SessionHandle=%u", ckSessionHandle); - TRACE0(" ... "); - - jSessionHandle = ckULongToJLong(ckSessionHandle); - -#ifndef NO_CALLBACKS - if (notifyEncapsulation != NULL) { - /* store the notifyEncapsulation to enable later cleanup */ - putNotifyEntry(env, ckSessionHandle, notifyEncapsulation); - } -#endif /* NO_CALLBACKS */ - - TRACE0("FINISHED\n"); - - return jSessionHandle ; -} -#endif - -#ifdef P11_ENABLE_C_CLOSESESSION -/* - * Class: sun_security_pkcs11_wrapper_PKCS11 - * Method: C_CloseSession - * Signature: (J)V - * Parametermapping: *PKCS11* - * @param jlong jSessionHandle CK_SESSION_HANDLE hSession - */ -JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1CloseSession - (JNIEnv *env, jobject obj, jlong jSessionHandle) -{ - CK_SESSION_HANDLE ckSessionHandle; - CK_RV rv; -#ifndef NO_CALLBACKS - NotifyEncapsulation *notifyEncapsulation; - jobject jApplicationData; -#endif /* NO_CALLBACKS */ - - CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj); - if (ckpFunctions == NULL) { return; } - - ckSessionHandle = jLongToCKULong(jSessionHandle); - - rv = (*ckpFunctions->C_CloseSession)(ckSessionHandle); - if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; } - -#ifndef NO_CALLBACKS - notifyEncapsulation = removeNotifyEntry(env, ckSessionHandle); - - if (notifyEncapsulation != NULL) { - /* there was a notify object used with this session, now dump the - * encapsulation object - */ - (*env)->DeleteGlobalRef(env, notifyEncapsulation->jNotifyObject); - jApplicationData = notifyEncapsulation->jApplicationData; - if (jApplicationData != NULL) { - (*env)->DeleteGlobalRef(env, jApplicationData); - } - free(notifyEncapsulation); - } -#endif /* NO_CALLBACKS */ - -} -#endif - -#ifdef P11_ENABLE_C_CLOSEALLSESSIONS -/* - * Class: sun_security_pkcs11_wrapper_PKCS11 - * Method: C_CloseAllSessions - * Signature: (J)V - * Parametermapping: *PKCS11* - * @param jlong jSlotID CK_SLOT_ID slotID - */ -JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1CloseAllSessions - (JNIEnv *env, jobject obj, jlong jSlotID) -{ - CK_SLOT_ID ckSlotID; - CK_RV rv; -#ifndef NO_CALLBACKS - NotifyEncapsulation *notifyEncapsulation; - jobject jApplicationData; -#endif /* NO_CALLBACKS */ - - CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj); - if (ckpFunctions == NULL) { return; } - - ckSlotID = jLongToCKULong(jSlotID); - - rv = (*ckpFunctions->C_CloseAllSessions)(ckSlotID); - if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; } - -#ifndef NO_CALLBACKS - /* Remove all notify callback helper objects. */ - while ((notifyEncapsulation = removeFirstNotifyEntry(env)) != NULL) { - /* there was a notify object used with this session, now dump the - * encapsulation object - */ - (*env)->DeleteGlobalRef(env, notifyEncapsulation->jNotifyObject); - jApplicationData = notifyEncapsulation->jApplicationData; - if (jApplicationData != NULL) { - (*env)->DeleteGlobalRef(env, jApplicationData); - } - free(notifyEncapsulation); - } -#endif /* NO_CALLBACKS */ -} -#endif - -#ifdef P11_ENABLE_C_GETSESSIONINFO -/* - * Class: sun_security_pkcs11_wrapper_PKCS11 - * Method: C_GetSessionInfo - * Signature: (J)Lsun/security/pkcs11/wrapper/CK_SESSION_INFO; - * Parametermapping: *PKCS11* - * @param jlong jSessionHandle CK_SESSION_HANDLE hSession - * @return jobject jSessionInfo CK_SESSION_INFO_PTR pInfo - */ -JNIEXPORT jobject JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1GetSessionInfo - (JNIEnv *env, jobject obj, jlong jSessionHandle) -{ - CK_SESSION_HANDLE ckSessionHandle; - CK_SESSION_INFO ckSessionInfo; - jobject jSessionInfo=NULL; - CK_RV rv; - - CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj); - if (ckpFunctions == NULL) { return NULL; } - - ckSessionHandle = jLongToCKULong(jSessionHandle); - - rv = (*ckpFunctions->C_GetSessionInfo)(ckSessionHandle, &ckSessionInfo); - if (ckAssertReturnValueOK(env, rv) == CK_ASSERT_OK) { - jSessionInfo = ckSessionInfoPtrToJSessionInfo(env, &ckSessionInfo); - } - return jSessionInfo ; -} -#endif - -#ifdef P11_ENABLE_C_GETOPERATIONSTATE -/* - * Class: sun_security_pkcs11_wrapper_PKCS11 - * Method: C_GetOperationState - * Signature: (J)[B - * Parametermapping: *PKCS11* - * @param jlong jSessionHandle CK_SESSION_HANDLE hSession - * @return jbyteArray jState CK_BYTE_PTR pOperationState - * CK_ULONG_PTR pulOperationStateLen - */ -JNIEXPORT jbyteArray JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1GetOperationState - (JNIEnv *env, jobject obj, jlong jSessionHandle) -{ - CK_SESSION_HANDLE ckSessionHandle; - CK_BYTE_PTR ckpState; - CK_ULONG ckStateLength; - jbyteArray jState = NULL; - CK_RV rv; - - CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj); - if (ckpFunctions == NULL) { return NULL; } - - ckSessionHandle = jLongToCKULong(jSessionHandle); - - rv = (*ckpFunctions->C_GetOperationState)(ckSessionHandle, NULL_PTR, &ckStateLength); - if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return NULL ; } - - ckpState = (CK_BYTE_PTR) malloc(ckStateLength); - if (ckpState == NULL) { - throwOutOfMemoryError(env, 0); - return NULL; - } - - rv = (*ckpFunctions->C_GetOperationState)(ckSessionHandle, ckpState, &ckStateLength); - if (ckAssertReturnValueOK(env, rv) == CK_ASSERT_OK) { - jState = ckByteArrayToJByteArray(env, ckpState, ckStateLength); - } - free(ckpState); - - return jState ; -} -#endif - -#ifdef P11_ENABLE_C_SETOPERATIONSTATE -/* - * Class: sun_security_pkcs11_wrapper_PKCS11 - * Method: C_SetOperationState - * Signature: (J[BJJ)V - * Parametermapping: *PKCS11* - * @param jlong jSessionHandle CK_SESSION_HANDLE hSession - * @param jbyteArray jOperationState CK_BYTE_PTR pOperationState - * CK_ULONG ulOperationStateLen - * @param jlong jEncryptionKeyHandle CK_OBJECT_HANDLE hEncryptionKey - * @param jlong jAuthenticationKeyHandle CK_OBJECT_HANDLE hAuthenticationKey - */ -JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1SetOperationState - (JNIEnv *env, jobject obj, jlong jSessionHandle, jbyteArray jOperationState, jlong jEncryptionKeyHandle, jlong jAuthenticationKeyHandle) -{ - CK_SESSION_HANDLE ckSessionHandle; - CK_BYTE_PTR ckpState = NULL_PTR; - CK_ULONG ckStateLength; - CK_OBJECT_HANDLE ckEncryptionKeyHandle; - CK_OBJECT_HANDLE ckAuthenticationKeyHandle; - CK_RV rv; - - CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj); - if (ckpFunctions == NULL) { return; } - - ckSessionHandle = jLongToCKULong(jSessionHandle); - jByteArrayToCKByteArray(env, jOperationState, &ckpState, &ckStateLength); - if ((*env)->ExceptionCheck(env)) { return; } - - ckEncryptionKeyHandle = jLongToCKULong(jEncryptionKeyHandle); - ckAuthenticationKeyHandle = jLongToCKULong(jAuthenticationKeyHandle); - - rv = (*ckpFunctions->C_SetOperationState)(ckSessionHandle, ckpState, ckStateLength, ckEncryptionKeyHandle, ckAuthenticationKeyHandle); - - free(ckpState); - - if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; } -} -#endif - -#ifdef P11_ENABLE_C_LOGIN -/* - * Class: sun_security_pkcs11_wrapper_PKCS11 - * Method: C_Login - * Signature: (JJ[C)V - * Parametermapping: *PKCS11* - * @param jlong jSessionHandle CK_SESSION_HANDLE hSession - * @param jlong jUserType CK_USER_TYPE userType - * @param jcharArray jPin CK_CHAR_PTR pPin - * CK_ULONG ulPinLen - */ -JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1Login - (JNIEnv *env, jobject obj, jlong jSessionHandle, jlong jUserType, jcharArray jPin) -{ - CK_SESSION_HANDLE ckSessionHandle; - CK_USER_TYPE ckUserType; - CK_CHAR_PTR ckpPinArray = NULL_PTR; - CK_ULONG ckPinLength; - CK_RV rv; - - CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj); - if (ckpFunctions == NULL) { return; } - - ckSessionHandle = jLongToCKULong(jSessionHandle); - ckUserType = jLongToCKULong(jUserType); - jCharArrayToCKCharArray(env, jPin, &ckpPinArray, &ckPinLength); - if ((*env)->ExceptionCheck(env)) { return; } - - rv = (*ckpFunctions->C_Login)(ckSessionHandle, ckUserType, ckpPinArray, ckPinLength); - - free(ckpPinArray); - - if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; } -} -#endif - -#ifdef P11_ENABLE_C_LOGOUT -/* - * Class: sun_security_pkcs11_wrapper_PKCS11 - * Method: C_Logout - * Signature: (J)V - * Parametermapping: *PKCS11* - * @param jlong jSessionHandle CK_SESSION_HANDLE hSession - */ -JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1Logout - (JNIEnv *env, jobject obj, jlong jSessionHandle) -{ - CK_SESSION_HANDLE ckSessionHandle; - CK_RV rv; - - CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj); - if (ckpFunctions == NULL) { return; } - - ckSessionHandle = jLongToCKULong(jSessionHandle); - - rv = (*ckpFunctions->C_Logout)(ckSessionHandle); - if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; } -} -#endif - -/* ************************************************************************** */ -/* Functions for keeping track of notify callbacks */ -/* ************************************************************************** */ - -#ifndef NO_CALLBACKS - -/* - * Add the given notify encapsulation object to the list of active notify - * objects. - * If notifyEncapsulation is NULL, this function does nothing. - */ -void putNotifyEntry(JNIEnv *env, CK_SESSION_HANDLE hSession, NotifyEncapsulation *notifyEncapsulation) { - NotifyListNode *currentNode, *newNode; - - if (notifyEncapsulation == NULL) { - return; - } - - newNode = (NotifyListNode *) malloc(sizeof(NotifyListNode)); - if (newNode == NULL) { - throwOutOfMemoryError(env, 0); - return; - } - newNode->hSession = hSession; - newNode->notifyEncapsulation = notifyEncapsulation; - newNode->next = NULL; - - (*env)->MonitorEnter(env, notifyListLock); /* synchronize access to list */ - - if (notifyListHead == NULL) { - /* this is the first entry */ - notifyListHead = newNode; - } else { - /* go to the last entry; i.e. the first node which's 'next' is NULL. - */ - currentNode = notifyListHead; - while (currentNode->next != NULL) { - currentNode = currentNode->next; - } - currentNode->next = newNode; - } - - (*env)->MonitorExit(env, notifyListLock); /* synchronize access to list */ -} - -/* - * Removes the active notifyEncapsulation object used with the given session and - * returns it. If there is no notifyEncapsulation active for this session, this - * function returns NULL. - */ -NotifyEncapsulation * removeNotifyEntry(JNIEnv *env, CK_SESSION_HANDLE hSession) { - NotifyEncapsulation *notifyEncapsulation; - NotifyListNode *currentNode, *previousNode; - - (*env)->MonitorEnter(env, notifyListLock); /* synchronize access to list */ - - if (notifyListHead == NULL) { - /* this is the first entry */ - notifyEncapsulation = NULL; - } else { - /* Find the node with the wanted session handle. Also stop, when we reach - * the last entry; i.e. the first node which's 'next' is NULL. - */ - currentNode = notifyListHead; - previousNode = NULL; - - while ((currentNode->hSession != hSession) && (currentNode->next != NULL)) { - previousNode = currentNode; - currentNode = currentNode->next; - } - - if (currentNode->hSession == hSession) { - /* We found a entry for the wanted session, now remove it. */ - if (previousNode == NULL) { - /* it's the first node */ - notifyListHead = currentNode->next; - } else { - previousNode->next = currentNode->next; - } - notifyEncapsulation = currentNode->notifyEncapsulation; - free(currentNode); - } else { - /* We did not find a entry for this session */ - notifyEncapsulation = NULL; - } - } - - (*env)->MonitorExit(env, notifyListLock); /* synchronize access to list */ - - return notifyEncapsulation ; -} - -/* - - * Removes the first notifyEncapsulation object. If there is no notifyEncapsulation, - * this function returns NULL. - */ -NotifyEncapsulation * removeFirstNotifyEntry(JNIEnv *env) { - NotifyEncapsulation *notifyEncapsulation; - NotifyListNode *currentNode; - - (*env)->MonitorEnter(env, notifyListLock); /* synchronize access to list */ - - if (notifyListHead == NULL) { - /* this is the first entry */ - notifyEncapsulation = NULL; - } else { - /* Remove the first entry. */ - currentNode = notifyListHead; - notifyListHead = notifyListHead->next; - notifyEncapsulation = currentNode->notifyEncapsulation; - free(currentNode); - } - - (*env)->MonitorExit(env, notifyListLock); /* synchronize access to list */ - - return notifyEncapsulation ; -} - -#endif /* NO_CALLBACKS */ - -#ifndef NO_CALLBACKS - -/* - * The function handling notify callbacks. It casts the pApplication parameter - * back to a NotifyEncapsulation structure and retrieves the Notify object and - * the application data from it. - * - * @param hSession The session, this callback is comming from. - * @param event The type of event that occurred. - * @param pApplication The application data as passed in upon OpenSession. In - this wrapper we always pass in a NotifyEncapsulation - object, which holds necessary information for delegating - the callback to the Java VM. - * @return - */ -CK_RV notifyCallback( - CK_SESSION_HANDLE hSession, /* the session's handle */ - CK_NOTIFICATION event, - CK_VOID_PTR pApplication /* passed to C_OpenSession */ -) -{ - NotifyEncapsulation *notifyEncapsulation; - extern JavaVM *jvm; - JNIEnv *env; - jint returnValue; - jlong jSessionHandle; - jlong jEvent; - jclass ckNotifyClass; - jmethodID jmethod; - jthrowable pkcs11Exception; - jclass pkcs11ExceptionClass; - jlong errorCode; - CK_RV rv = CKR_OK; - int wasAttached = 1; - - if (pApplication == NULL) { return rv ; } /* This should not occur in this wrapper. */ - - notifyEncapsulation = (NotifyEncapsulation *) pApplication; - - /* 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; - } - - jSessionHandle = ckULongToJLong(hSession); - jEvent = ckULongToJLong(event); - - ckNotifyClass = (*env)->FindClass(env, CLASS_NOTIFY); - if (ckNotifyClass == NULL) { return rv; } - jmethod = (*env)->GetMethodID(env, ckNotifyClass, "CK_NOTIFY", "(JJLjava/lang/Object;)V"); - if (jmethod == NULL) { return rv; } - - (*env)->CallVoidMethod(env, notifyEncapsulation->jNotifyObject, jmethod, - jSessionHandle, jEvent, notifyEncapsulation->jApplicationData); - - /* 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; } - - jmethod = (*env)->GetMethodID(env, pkcs11ExceptionClass, "getErrorCode", "()J"); - if (jmethod == NULL) { return rv; } - - errorCode = (*env)->CallLongMethod(env, pkcs11Exception, jmethod); - 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 2017-01-18 09:30:05.425422781 -0800 +++ new/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_sessmgmt.c 2017-01-20 09:52:58.070288211 -0800 @@ -0,0 +1,634 @@ +/* + * Copyright (c) 2003, 2013, 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 list of notify callback handles that are currently active and waiting + * for callbacks from their sessions. + */ +#ifndef NO_CALLBACKS +NotifyListNode *notifyListHead = NULL; +jobject notifyListLock = NULL; +#endif /* NO_CALLBACKS */ + +#ifdef P11_ENABLE_C_OPENSESSION +/* + * Class: sun_security_pkcs11_wrapper_PKCS11 + * Method: C_OpenSession + * Signature: (JJLjava/lang/Object;Lsun/security/pkcs11/wrapper/CK_NOTIFY;)J + * Parametermapping: *PKCS11* + * @param jlong jSlotID CK_SLOT_ID slotID + * @param jlong jFlags CK_FLAGS flags + * @param jobject jApplication CK_VOID_PTR pApplication + * @param jobject jNotify CK_NOTIFY Notify + * @return jlong jSessionHandle CK_SESSION_HANDLE_PTR phSession + */ +JNIEXPORT jlong JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1OpenSession + (JNIEnv *env, jobject obj, jlong jSlotID, jlong jFlags, jobject jApplication, jobject jNotify) +{ + CK_SESSION_HANDLE ckSessionHandle; + CK_SLOT_ID ckSlotID; + CK_FLAGS ckFlags; + CK_VOID_PTR ckpApplication; + CK_NOTIFY ckNotify; + jlong jSessionHandle; + CK_RV rv; +#ifndef NO_CALLBACKS + NotifyEncapsulation *notifyEncapsulation = NULL; +#endif /* NO_CALLBACKS */ + + CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj); + if (ckpFunctions == NULL) { return 0L; } + + ckSlotID = jLongToCKULong(jSlotID); + ckFlags = jLongToCKULong(jFlags); + +#ifndef NO_CALLBACKS + if (jNotify != NULL) { + notifyEncapsulation = (NotifyEncapsulation *) malloc(sizeof(NotifyEncapsulation)); + if (notifyEncapsulation == NULL) { + throwOutOfMemoryError(env, 0); + return 0L; + } + notifyEncapsulation->jApplicationData = (jApplication != NULL) + ? (*env)->NewGlobalRef(env, jApplication) + : NULL; + notifyEncapsulation->jNotifyObject = (*env)->NewGlobalRef(env, jNotify); + ckpApplication = notifyEncapsulation; + ckNotify = (CK_NOTIFY) ¬ifyCallback; + } else { + ckpApplication = NULL_PTR; + ckNotify = NULL_PTR; + } +#else + ckpApplication = NULL_PTR; + ckNotify = NULL_PTR; +#endif /* NO_CALLBACKS */ + + TRACE0("DEBUG: C_OpenSession"); + TRACE1(", slotID=%u", ckSlotID); + TRACE1(", flags=%x", ckFlags); + TRACE0(" ... "); + + rv = (*ckpFunctions->C_OpenSession)(ckSlotID, ckFlags, ckpApplication, ckNotify, &ckSessionHandle); + if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { +#ifndef NO_CALLBACKS + if (notifyEncapsulation != NULL) { + if (notifyEncapsulation->jApplicationData != NULL) { + (*env)->DeleteGlobalRef(env, jApplication); + } + (*env)->DeleteGlobalRef(env, jNotify); + free(notifyEncapsulation); + } +#endif /* NO_CALLBACKS */ + return 0L; + } + + TRACE0("got session"); + TRACE1(", SessionHandle=%u", ckSessionHandle); + TRACE0(" ... "); + + jSessionHandle = ckULongToJLong(ckSessionHandle); + +#ifndef NO_CALLBACKS + if (notifyEncapsulation != NULL) { + /* store the notifyEncapsulation to enable later cleanup */ + putNotifyEntry(env, ckSessionHandle, notifyEncapsulation); + } +#endif /* NO_CALLBACKS */ + + TRACE0("FINISHED\n"); + + return jSessionHandle ; +} +#endif + +#ifdef P11_ENABLE_C_CLOSESESSION +/* + * Class: sun_security_pkcs11_wrapper_PKCS11 + * Method: C_CloseSession + * Signature: (J)V + * Parametermapping: *PKCS11* + * @param jlong jSessionHandle CK_SESSION_HANDLE hSession + */ +JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1CloseSession + (JNIEnv *env, jobject obj, jlong jSessionHandle) +{ + CK_SESSION_HANDLE ckSessionHandle; + CK_RV rv; +#ifndef NO_CALLBACKS + NotifyEncapsulation *notifyEncapsulation; + jobject jApplicationData; +#endif /* NO_CALLBACKS */ + + CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj); + if (ckpFunctions == NULL) { return; } + + ckSessionHandle = jLongToCKULong(jSessionHandle); + + rv = (*ckpFunctions->C_CloseSession)(ckSessionHandle); + if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; } + +#ifndef NO_CALLBACKS + notifyEncapsulation = removeNotifyEntry(env, ckSessionHandle); + + if (notifyEncapsulation != NULL) { + /* there was a notify object used with this session, now dump the + * encapsulation object + */ + (*env)->DeleteGlobalRef(env, notifyEncapsulation->jNotifyObject); + jApplicationData = notifyEncapsulation->jApplicationData; + if (jApplicationData != NULL) { + (*env)->DeleteGlobalRef(env, jApplicationData); + } + free(notifyEncapsulation); + } +#endif /* NO_CALLBACKS */ + +} +#endif + +#ifdef P11_ENABLE_C_CLOSEALLSESSIONS +/* + * Class: sun_security_pkcs11_wrapper_PKCS11 + * Method: C_CloseAllSessions + * Signature: (J)V + * Parametermapping: *PKCS11* + * @param jlong jSlotID CK_SLOT_ID slotID + */ +JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1CloseAllSessions + (JNIEnv *env, jobject obj, jlong jSlotID) +{ + CK_SLOT_ID ckSlotID; + CK_RV rv; +#ifndef NO_CALLBACKS + NotifyEncapsulation *notifyEncapsulation; + jobject jApplicationData; +#endif /* NO_CALLBACKS */ + + CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj); + if (ckpFunctions == NULL) { return; } + + ckSlotID = jLongToCKULong(jSlotID); + + rv = (*ckpFunctions->C_CloseAllSessions)(ckSlotID); + if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; } + +#ifndef NO_CALLBACKS + /* Remove all notify callback helper objects. */ + while ((notifyEncapsulation = removeFirstNotifyEntry(env)) != NULL) { + /* there was a notify object used with this session, now dump the + * encapsulation object + */ + (*env)->DeleteGlobalRef(env, notifyEncapsulation->jNotifyObject); + jApplicationData = notifyEncapsulation->jApplicationData; + if (jApplicationData != NULL) { + (*env)->DeleteGlobalRef(env, jApplicationData); + } + free(notifyEncapsulation); + } +#endif /* NO_CALLBACKS */ +} +#endif + +#ifdef P11_ENABLE_C_GETSESSIONINFO +/* + * Class: sun_security_pkcs11_wrapper_PKCS11 + * Method: C_GetSessionInfo + * Signature: (J)Lsun/security/pkcs11/wrapper/CK_SESSION_INFO; + * Parametermapping: *PKCS11* + * @param jlong jSessionHandle CK_SESSION_HANDLE hSession + * @return jobject jSessionInfo CK_SESSION_INFO_PTR pInfo + */ +JNIEXPORT jobject JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1GetSessionInfo + (JNIEnv *env, jobject obj, jlong jSessionHandle) +{ + CK_SESSION_HANDLE ckSessionHandle; + CK_SESSION_INFO ckSessionInfo; + jobject jSessionInfo=NULL; + CK_RV rv; + + CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj); + if (ckpFunctions == NULL) { return NULL; } + + ckSessionHandle = jLongToCKULong(jSessionHandle); + + rv = (*ckpFunctions->C_GetSessionInfo)(ckSessionHandle, &ckSessionInfo); + if (ckAssertReturnValueOK(env, rv) == CK_ASSERT_OK) { + jSessionInfo = ckSessionInfoPtrToJSessionInfo(env, &ckSessionInfo); + } + return jSessionInfo ; +} +#endif + +#ifdef P11_ENABLE_C_GETOPERATIONSTATE +/* + * Class: sun_security_pkcs11_wrapper_PKCS11 + * Method: C_GetOperationState + * Signature: (J)[B + * Parametermapping: *PKCS11* + * @param jlong jSessionHandle CK_SESSION_HANDLE hSession + * @return jbyteArray jState CK_BYTE_PTR pOperationState + * CK_ULONG_PTR pulOperationStateLen + */ +JNIEXPORT jbyteArray JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1GetOperationState + (JNIEnv *env, jobject obj, jlong jSessionHandle) +{ + CK_SESSION_HANDLE ckSessionHandle; + CK_BYTE_PTR ckpState; + CK_ULONG ckStateLength; + jbyteArray jState = NULL; + CK_RV rv; + + CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj); + if (ckpFunctions == NULL) { return NULL; } + + ckSessionHandle = jLongToCKULong(jSessionHandle); + + rv = (*ckpFunctions->C_GetOperationState)(ckSessionHandle, NULL_PTR, &ckStateLength); + if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return NULL ; } + + ckpState = (CK_BYTE_PTR) malloc(ckStateLength); + if (ckpState == NULL) { + throwOutOfMemoryError(env, 0); + return NULL; + } + + rv = (*ckpFunctions->C_GetOperationState)(ckSessionHandle, ckpState, &ckStateLength); + if (ckAssertReturnValueOK(env, rv) == CK_ASSERT_OK) { + jState = ckByteArrayToJByteArray(env, ckpState, ckStateLength); + } + free(ckpState); + + return jState ; +} +#endif + +#ifdef P11_ENABLE_C_SETOPERATIONSTATE +/* + * Class: sun_security_pkcs11_wrapper_PKCS11 + * Method: C_SetOperationState + * Signature: (J[BJJ)V + * Parametermapping: *PKCS11* + * @param jlong jSessionHandle CK_SESSION_HANDLE hSession + * @param jbyteArray jOperationState CK_BYTE_PTR pOperationState + * CK_ULONG ulOperationStateLen + * @param jlong jEncryptionKeyHandle CK_OBJECT_HANDLE hEncryptionKey + * @param jlong jAuthenticationKeyHandle CK_OBJECT_HANDLE hAuthenticationKey + */ +JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1SetOperationState + (JNIEnv *env, jobject obj, jlong jSessionHandle, jbyteArray jOperationState, jlong jEncryptionKeyHandle, jlong jAuthenticationKeyHandle) +{ + CK_SESSION_HANDLE ckSessionHandle; + CK_BYTE_PTR ckpState = NULL_PTR; + CK_ULONG ckStateLength; + CK_OBJECT_HANDLE ckEncryptionKeyHandle; + CK_OBJECT_HANDLE ckAuthenticationKeyHandle; + CK_RV rv; + + CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj); + if (ckpFunctions == NULL) { return; } + + ckSessionHandle = jLongToCKULong(jSessionHandle); + jByteArrayToCKByteArray(env, jOperationState, &ckpState, &ckStateLength); + if ((*env)->ExceptionCheck(env)) { return; } + + ckEncryptionKeyHandle = jLongToCKULong(jEncryptionKeyHandle); + ckAuthenticationKeyHandle = jLongToCKULong(jAuthenticationKeyHandle); + + rv = (*ckpFunctions->C_SetOperationState)(ckSessionHandle, ckpState, ckStateLength, ckEncryptionKeyHandle, ckAuthenticationKeyHandle); + + free(ckpState); + + if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; } +} +#endif + +#ifdef P11_ENABLE_C_LOGIN +/* + * Class: sun_security_pkcs11_wrapper_PKCS11 + * Method: C_Login + * Signature: (JJ[C)V + * Parametermapping: *PKCS11* + * @param jlong jSessionHandle CK_SESSION_HANDLE hSession + * @param jlong jUserType CK_USER_TYPE userType + * @param jcharArray jPin CK_CHAR_PTR pPin + * CK_ULONG ulPinLen + */ +JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1Login + (JNIEnv *env, jobject obj, jlong jSessionHandle, jlong jUserType, jcharArray jPin) +{ + CK_SESSION_HANDLE ckSessionHandle; + CK_USER_TYPE ckUserType; + CK_CHAR_PTR ckpPinArray = NULL_PTR; + CK_ULONG ckPinLength; + CK_RV rv; + + CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj); + if (ckpFunctions == NULL) { return; } + + ckSessionHandle = jLongToCKULong(jSessionHandle); + ckUserType = jLongToCKULong(jUserType); + jCharArrayToCKCharArray(env, jPin, &ckpPinArray, &ckPinLength); + if ((*env)->ExceptionCheck(env)) { return; } + + rv = (*ckpFunctions->C_Login)(ckSessionHandle, ckUserType, ckpPinArray, ckPinLength); + + free(ckpPinArray); + + if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; } +} +#endif + +#ifdef P11_ENABLE_C_LOGOUT +/* + * Class: sun_security_pkcs11_wrapper_PKCS11 + * Method: C_Logout + * Signature: (J)V + * Parametermapping: *PKCS11* + * @param jlong jSessionHandle CK_SESSION_HANDLE hSession + */ +JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1Logout + (JNIEnv *env, jobject obj, jlong jSessionHandle) +{ + CK_SESSION_HANDLE ckSessionHandle; + CK_RV rv; + + CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj); + if (ckpFunctions == NULL) { return; } + + ckSessionHandle = jLongToCKULong(jSessionHandle); + + rv = (*ckpFunctions->C_Logout)(ckSessionHandle); + if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; } +} +#endif + +/* ************************************************************************** */ +/* Functions for keeping track of notify callbacks */ +/* ************************************************************************** */ + +#ifndef NO_CALLBACKS + +/* + * Add the given notify encapsulation object to the list of active notify + * objects. + * If notifyEncapsulation is NULL, this function does nothing. + */ +void putNotifyEntry(JNIEnv *env, CK_SESSION_HANDLE hSession, NotifyEncapsulation *notifyEncapsulation) { + NotifyListNode *currentNode, *newNode; + + if (notifyEncapsulation == NULL) { + return; + } + + newNode = (NotifyListNode *) malloc(sizeof(NotifyListNode)); + if (newNode == NULL) { + throwOutOfMemoryError(env, 0); + return; + } + newNode->hSession = hSession; + newNode->notifyEncapsulation = notifyEncapsulation; + newNode->next = NULL; + + (*env)->MonitorEnter(env, notifyListLock); /* synchronize access to list */ + + if (notifyListHead == NULL) { + /* this is the first entry */ + notifyListHead = newNode; + } else { + /* go to the last entry; i.e. the first node which's 'next' is NULL. + */ + currentNode = notifyListHead; + while (currentNode->next != NULL) { + currentNode = currentNode->next; + } + currentNode->next = newNode; + } + + (*env)->MonitorExit(env, notifyListLock); /* synchronize access to list */ +} + +/* + * Removes the active notifyEncapsulation object used with the given session and + * returns it. If there is no notifyEncapsulation active for this session, this + * function returns NULL. + */ +NotifyEncapsulation * removeNotifyEntry(JNIEnv *env, CK_SESSION_HANDLE hSession) { + NotifyEncapsulation *notifyEncapsulation; + NotifyListNode *currentNode, *previousNode; + + (*env)->MonitorEnter(env, notifyListLock); /* synchronize access to list */ + + if (notifyListHead == NULL) { + /* this is the first entry */ + notifyEncapsulation = NULL; + } else { + /* Find the node with the wanted session handle. Also stop, when we reach + * the last entry; i.e. the first node which's 'next' is NULL. + */ + currentNode = notifyListHead; + previousNode = NULL; + + while ((currentNode->hSession != hSession) && (currentNode->next != NULL)) { + previousNode = currentNode; + currentNode = currentNode->next; + } + + if (currentNode->hSession == hSession) { + /* We found a entry for the wanted session, now remove it. */ + if (previousNode == NULL) { + /* it's the first node */ + notifyListHead = currentNode->next; + } else { + previousNode->next = currentNode->next; + } + notifyEncapsulation = currentNode->notifyEncapsulation; + free(currentNode); + } else { + /* We did not find a entry for this session */ + notifyEncapsulation = NULL; + } + } + + (*env)->MonitorExit(env, notifyListLock); /* synchronize access to list */ + + return notifyEncapsulation ; +} + +/* + + * Removes the first notifyEncapsulation object. If there is no notifyEncapsulation, + * this function returns NULL. + */ +NotifyEncapsulation * removeFirstNotifyEntry(JNIEnv *env) { + NotifyEncapsulation *notifyEncapsulation; + NotifyListNode *currentNode; + + (*env)->MonitorEnter(env, notifyListLock); /* synchronize access to list */ + + if (notifyListHead == NULL) { + /* this is the first entry */ + notifyEncapsulation = NULL; + } else { + /* Remove the first entry. */ + currentNode = notifyListHead; + notifyListHead = notifyListHead->next; + notifyEncapsulation = currentNode->notifyEncapsulation; + free(currentNode); + } + + (*env)->MonitorExit(env, notifyListLock); /* synchronize access to list */ + + return notifyEncapsulation ; +} + +#endif /* NO_CALLBACKS */ + +#ifndef NO_CALLBACKS + +/* + * The function handling notify callbacks. It casts the pApplication parameter + * back to a NotifyEncapsulation structure and retrieves the Notify object and + * the application data from it. + * + * @param hSession The session, this callback is comming from. + * @param event The type of event that occurred. + * @param pApplication The application data as passed in upon OpenSession. In + this wrapper we always pass in a NotifyEncapsulation + object, which holds necessary information for delegating + the callback to the Java VM. + * @return + */ +CK_RV notifyCallback( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_NOTIFICATION event, + CK_VOID_PTR pApplication /* passed to C_OpenSession */ +) +{ + NotifyEncapsulation *notifyEncapsulation; + extern JavaVM *jvm; + JNIEnv *env; + jint returnValue; + jlong jSessionHandle; + jlong jEvent; + jclass ckNotifyClass; + jmethodID jmethod; + jthrowable pkcs11Exception; + jclass pkcs11ExceptionClass; + jlong errorCode; + CK_RV rv = CKR_OK; + int wasAttached = 1; + + if (pApplication == NULL) { return rv ; } /* This should not occur in this wrapper. */ + + notifyEncapsulation = (NotifyEncapsulation *) pApplication; + + /* 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; + } + + jSessionHandle = ckULongToJLong(hSession); + jEvent = ckULongToJLong(event); + + ckNotifyClass = (*env)->FindClass(env, CLASS_NOTIFY); + if (ckNotifyClass == NULL) { return rv; } + jmethod = (*env)->GetMethodID(env, ckNotifyClass, "CK_NOTIFY", "(JJLjava/lang/Object;)V"); + if (jmethod == NULL) { return rv; } + + (*env)->CallVoidMethod(env, notifyEncapsulation->jNotifyObject, jmethod, + jSessionHandle, jEvent, notifyEncapsulation->jApplicationData); + + /* 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; } + + jmethod = (*env)->GetMethodID(env, pkcs11ExceptionClass, "getErrorCode", "()J"); + if (jmethod == NULL) { return rv; } + + errorCode = (*env)->CallLongMethod(env, pkcs11Exception, jmethod); + 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 */