Path: blob/master/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_mutex.c
41149 views
/*1* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.2*/34/* Copyright (c) 2002 Graz University of Technology. All rights reserved.5*6* Redistribution and use in source and binary forms, with or without7* modification, are permitted provided that the following conditions are met:8*9* 1. Redistributions of source code must retain the above copyright notice,10* this list of conditions and the following disclaimer.11*12* 2. Redistributions in binary form must reproduce the above copyright notice,13* this list of conditions and the following disclaimer in the documentation14* and/or other materials provided with the distribution.15*16* 3. The end-user documentation included with the redistribution, if any, must17* include the following acknowledgment:18*19* "This product includes software developed by IAIK of Graz University of20* Technology."21*22* Alternately, this acknowledgment may appear in the software itself, if23* and wherever such third-party acknowledgments normally appear.24*25* 4. The names "Graz University of Technology" and "IAIK of Graz University of26* Technology" must not be used to endorse or promote products derived from27* this software without prior written permission.28*29* 5. Products derived from this software may not be called30* "IAIK PKCS Wrapper", nor may "IAIK" appear in their name, without prior31* written permission of Graz University of Technology.32*33* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED34* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED35* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR36* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE37* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,38* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,39* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,40* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON41* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,42* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY43* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE44* POSSIBILITY OF SUCH DAMAGE.45*/4647#include "pkcs11wrapper.h"4849#include <stdio.h>50#include <stdlib.h>51#include <string.h>52#include <assert.h>5354#include "sun_security_pkcs11_wrapper_PKCS11.h"5556/* The initArgs that enable the application to do custom mutex-handling */57#ifndef NO_CALLBACKS58jobject jInitArgsObject;59CK_C_INITIALIZE_ARGS_PTR ckpGlobalInitArgs;60#endif /* NO_CALLBACKS */6162/* ************************************************************************** */63/* Now come the functions for mutex handling and notification callbacks */64/* ************************************************************************** */6566/*67* converts the InitArgs object to a CK_C_INITIALIZE_ARGS structure and sets the functions68* that will call the right Java mutex functions69*70* @param env - used to call JNI funktions to get the Java classes, objects, methods and fields71* @param pInitArgs - the InitArgs object with the Java mutex functions to call72* @return - the pointer to the CK_C_INITIALIZE_ARGS structure with the functions that will call73* the corresponding Java functions74*/75CK_C_INITIALIZE_ARGS_PTR makeCKInitArgsAdapter(JNIEnv *env, jobject jInitArgs)76{77CK_C_INITIALIZE_ARGS_PTR ckpInitArgs;78jclass jInitArgsClass;79jfieldID fieldID;80jlong jFlags;81jobject jReserved;82CK_ULONG ckReservedLength;83#ifndef NO_CALLBACKS84jobject jMutexHandler;85#endif /* NO_CALLBACKS */8687if(jInitArgs == NULL) {88return NULL_PTR;89}9091/* convert the Java InitArgs object to a pointer to a CK_C_INITIALIZE_ARGS structure */92ckpInitArgs = (CK_C_INITIALIZE_ARGS_PTR) malloc(sizeof(CK_C_INITIALIZE_ARGS));93if (ckpInitArgs == NULL) {94throwOutOfMemoryError(env, 0);95return NULL_PTR;96}97ckpInitArgs->flags = (CK_FLAGS)0;98ckpInitArgs->pReserved = (CK_VOID_PTR)NULL;99100/* Set the mutex functions that will call the Java mutex functions, but101* only set it, if the field is not null.102*/103jInitArgsClass = (*env)->FindClass(env, CLASS_C_INITIALIZE_ARGS);104if (jInitArgsClass == NULL) {105free(ckpInitArgs);106return NULL;107}108109#ifdef NO_CALLBACKS110ckpInitArgs->CreateMutex = NULL_PTR;111ckpInitArgs->DestroyMutex = NULL_PTR;112ckpInitArgs->LockMutex = NULL_PTR;113ckpInitArgs->UnlockMutex = NULL_PTR;114#else115fieldID = (*env)->GetFieldID(env, jInitArgsClass, "CreateMutex", "Lsun/security/pkcs11/wrapper/CK_CREATEMUTEX;");116if (fieldID == NULL) {117free(ckpInitArgs);118return NULL;119}120jMutexHandler = (*env)->GetObjectField(env, jInitArgs, fieldID);121ckpInitArgs->CreateMutex = (jMutexHandler != NULL) ? &callJCreateMutex : NULL_PTR;122123fieldID = (*env)->GetFieldID(env, jInitArgsClass, "DestroyMutex", "Lsun/security/pkcs11/wrapper/CK_DESTROYMUTEX;");124if (fieldID == NULL) {125free(ckpInitArgs);126return NULL;127}128jMutexHandler = (*env)->GetObjectField(env, jInitArgs, fieldID);129ckpInitArgs->DestroyMutex = (jMutexHandler != NULL) ? &callJDestroyMutex : NULL_PTR;130131fieldID = (*env)->GetFieldID(env, jInitArgsClass, "LockMutex", "Lsun/security/pkcs11/wrapper/CK_LOCKMUTEX;");132if (fieldID == NULL) {133free(ckpInitArgs);134return NULL;135}136jMutexHandler = (*env)->GetObjectField(env, jInitArgs, fieldID);137ckpInitArgs->LockMutex = (jMutexHandler != NULL) ? &callJLockMutex : NULL_PTR;138139fieldID = (*env)->GetFieldID(env, jInitArgsClass, "UnlockMutex", "Lsun/security/pkcs11/wrapper/CK_UNLOCKMUTEX;");140if (fieldID == NULL) {141free(ckpInitArgs);142return NULL;143}144jMutexHandler = (*env)->GetObjectField(env, jInitArgs, fieldID);145ckpInitArgs->UnlockMutex = (jMutexHandler != NULL) ? &callJUnlockMutex : NULL_PTR;146147if ((ckpInitArgs->CreateMutex != NULL_PTR)148|| (ckpInitArgs->DestroyMutex != NULL_PTR)149|| (ckpInitArgs->LockMutex != NULL_PTR)150|| (ckpInitArgs->UnlockMutex != NULL_PTR)) {151/* we only need to keep a global copy, if we need callbacks */152/* set the global object jInitArgs so that the right Java mutex functions will be called */153jInitArgsObject = (*env)->NewGlobalRef(env, jInitArgs);154ckpGlobalInitArgs = (CK_C_INITIALIZE_ARGS_PTR) malloc(sizeof(CK_C_INITIALIZE_ARGS));155if (ckpGlobalInitArgs == NULL) {156free(ckpInitArgs);157throwOutOfMemoryError(env, 0);158return NULL_PTR;159}160161memcpy(ckpGlobalInitArgs, ckpInitArgs, sizeof(CK_C_INITIALIZE_ARGS));162}163#endif /* NO_CALLBACKS */164165/* convert and set the flags field */166fieldID = (*env)->GetFieldID(env, jInitArgsClass, "flags", "J");167if (fieldID == NULL) {168free(ckpInitArgs);169return NULL;170}171jFlags = (*env)->GetLongField(env, jInitArgs, fieldID);172ckpInitArgs->flags = jLongToCKULong(jFlags);173174/* pReserved should be NULL_PTR in this version */175fieldID = (*env)->GetFieldID(env, jInitArgsClass, "pReserved", "Ljava/lang/Object;");176if (fieldID == NULL) {177free(ckpInitArgs);178return NULL;179}180jReserved = (*env)->GetObjectField(env, jInitArgs, fieldID);181182/* we try to convert the reserved parameter also */183ckpInitArgs->pReserved = jObjectToPrimitiveCKObjectPtr(env, jReserved, &ckReservedLength);184185return ckpInitArgs ;186}187188#ifndef NO_CALLBACKS189190/*191* is the function that gets called by PKCS#11 to create a mutex and calls the Java192* CreateMutex function193*194* @param env - used to call JNI funktions to get the Java classes, objects, methods and fields195* @param ppMutex - the new created mutex196* @return - should return CKR_OK if the mutex creation was ok197*/198CK_RV callJCreateMutex(CK_VOID_PTR_PTR ppMutex)199{200extern JavaVM *jvm;201JNIEnv *env;202jint returnValue;203jthrowable pkcs11Exception;204jclass pkcs11ExceptionClass;205jlong errorCode;206CK_RV rv = CKR_OK;207int wasAttached = 1;208jclass jCreateMutexClass;209jclass jInitArgsClass;210jmethodID methodID;211jfieldID fieldID;212jobject jCreateMutex;213jobject jMutex;214215216/* Get the currently running Java VM */217if (jvm == NULL) { return rv ;} /* there is no VM running */218219/* Determine, if current thread is already attached */220returnValue = (*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION_1_2);221if (returnValue == JNI_EDETACHED) {222/* thread detached, so attach it */223wasAttached = 0;224returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL);225} else if (returnValue == JNI_EVERSION) {226/* this version of JNI is not supported, so just try to attach */227/* we assume it was attached to ensure that this thread is not detached228* afterwards even though it should not229*/230wasAttached = 1;231returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL);232} else {233/* attached */234wasAttached = 1;235}236237jCreateMutexClass = (*env)->FindClass(env, CLASS_CREATEMUTEX);238if (jCreateMutexClass == NULL) { return rv; }239jInitArgsClass = (*env)->FindClass(env, CLASS_C_INITIALIZE_ARGS);240if (jInitArgsClass == NULL) { return rv; }241242/* get the CreateMutex object out of the jInitArgs object */243fieldID = (*env)->GetFieldID(env, jInitArgsClass, "CreateMutex", "Lsun/security/pkcs11/wrapper/CK_CREATEMUTEX;");244if (fieldID == NULL) { return rv; }245jCreateMutex = (*env)->GetObjectField(env, jInitArgsObject, fieldID);246assert(jCreateMutex != 0);247248/* call the CK_CREATEMUTEX function of the CreateMutex object */249/* and get the new Java mutex object */250methodID = (*env)->GetMethodID(env, jCreateMutexClass, "CK_CREATEMUTEX", "()Ljava/lang/Object;");251if (methodID == NULL) { return rv; }252jMutex = (*env)->CallObjectMethod(env, jCreateMutex, methodID);253254/* set a global reference on the Java mutex */255jMutex = (*env)->NewGlobalRef(env, jMutex);256/* convert the Java mutex to a CK mutex */257*ppMutex = jObjectToCKVoidPtr(jMutex);258259260/* check, if callback threw an exception */261pkcs11Exception = (*env)->ExceptionOccurred(env);262263if (pkcs11Exception != NULL) {264/* TBD: clear the pending exception with ExceptionClear? */265/* The was an exception thrown, now we get the error-code from it */266pkcs11ExceptionClass = (*env)->FindClass(env, CLASS_PKCS11EXCEPTION);267if (pkcs11ExceptionClass == NULL) { return rv; }268methodID = (*env)->GetMethodID(env, pkcs11ExceptionClass, "getErrorCode", "()J");269if (methodID == NULL) { return rv; }270271errorCode = (*env)->CallLongMethod(env, pkcs11Exception, methodID);272rv = jLongToCKULong(errorCode);273}274275/* if we attached this thread to the VM just for callback, we detach it now */276if (wasAttached) {277returnValue = (*jvm)->DetachCurrentThread(jvm);278}279280return rv ;281}282283/*284* is the function that gets called by PKCS#11 to destroy a mutex and calls the Java285* DestroyMutex function286*287* @param env - used to call JNI funktions to get the Java classes, objects, methods and fields288* @param pMutex - the mutex to destroy289* @return - should return CKR_OK if the mutex was destroyed290*/291CK_RV callJDestroyMutex(CK_VOID_PTR pMutex)292{293extern JavaVM *jvm;294JNIEnv *env;295jint returnValue;296jthrowable pkcs11Exception;297jclass pkcs11ExceptionClass;298jlong errorCode;299CK_RV rv = CKR_OK;300int wasAttached = 1;301jclass jDestroyMutexClass;302jclass jInitArgsClass;303jmethodID methodID;304jfieldID fieldID;305jobject jDestroyMutex;306jobject jMutex;307308309/* Get the currently running Java VM */310if (jvm == NULL) { return rv ; } /* there is no VM running */311312/* Determine, if current thread is already attached */313returnValue = (*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION_1_2);314if (returnValue == JNI_EDETACHED) {315/* thread detached, so attach it */316wasAttached = 0;317returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL);318} else if (returnValue == JNI_EVERSION) {319/* this version of JNI is not supported, so just try to attach */320/* we assume it was attached to ensure that this thread is not detached321* afterwards even though it should not322*/323wasAttached = 1;324returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL);325} else {326/* attached */327wasAttached = 1;328}329330jDestroyMutexClass = (*env)->FindClass(env, CLASS_DESTROYMUTEX);331if (jDestroyMutexClass == NULL) { return rv; }332jInitArgsClass = (*env)->FindClass(env, CLASS_C_INITIALIZE_ARGS);333if (jInitArgsClass == NULL) { return rv; }334335/* convert the CK mutex to a Java mutex */336jMutex = ckVoidPtrToJObject(pMutex);337338/* get the DestroyMutex object out of the jInitArgs object */339fieldID = (*env)->GetFieldID(env, jInitArgsClass, "DestroyMutex", "Lsun/security/pkcs11/wrapper/CK_DESTROYMUTEX;");340if (fieldID == NULL) { return rv; }341jDestroyMutex = (*env)->GetObjectField(env, jInitArgsObject, fieldID);342assert(jDestroyMutex != 0);343344/* call the CK_DESTROYMUTEX method of the DestroyMutex object */345methodID = (*env)->GetMethodID(env, jDestroyMutexClass, "CK_DESTROYMUTEX", "(Ljava/lang/Object;)V");346if (methodID == NULL) { return rv; }347(*env)->CallVoidMethod(env, jDestroyMutex, methodID, jMutex);348349/* delete the global reference on the Java mutex */350(*env)->DeleteGlobalRef(env, jMutex);351352353/* check, if callback threw an exception */354pkcs11Exception = (*env)->ExceptionOccurred(env);355356if (pkcs11Exception != NULL) {357/* TBD: clear the pending exception with ExceptionClear? */358/* The was an exception thrown, now we get the error-code from it */359pkcs11ExceptionClass = (*env)->FindClass(env, CLASS_PKCS11EXCEPTION);360if (pkcs11ExceptionClass == NULL) { return rv; }361methodID = (*env)->GetMethodID(env, pkcs11ExceptionClass, "getErrorCode", "()J");362if (methodID == NULL) { return rv; }363errorCode = (*env)->CallLongMethod(env, pkcs11Exception, methodID);364rv = jLongToCKULong(errorCode);365}366367/* if we attached this thread to the VM just for callback, we detach it now */368if (wasAttached) {369returnValue = (*jvm)->DetachCurrentThread(jvm);370}371372return rv ;373}374375/*376* is the function that gets called by PKCS#11 to lock a mutex and calls the Java377* LockMutex function378*379* @param env - used to call JNI funktions to get the Java classes, objects, methods and fields380* @param pMutex - the mutex to lock381* @return - should return CKR_OK if the mutex was not locked already382*/383CK_RV callJLockMutex(CK_VOID_PTR pMutex)384{385extern JavaVM *jvm;386JNIEnv *env;387jint returnValue;388jthrowable pkcs11Exception;389jclass pkcs11ExceptionClass;390jlong errorCode;391CK_RV rv = CKR_OK;392int wasAttached = 1;393jclass jLockMutexClass;394jclass jInitArgsClass;395jmethodID methodID;396jfieldID fieldID;397jobject jLockMutex;398jobject jMutex;399400401/* Get the currently running Java VM */402if (jvm == NULL) { return rv ; } /* there is no VM running */403404/* Determine, if current thread is already attached */405returnValue = (*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION_1_2);406if (returnValue == JNI_EDETACHED) {407/* thread detached, so attach it */408wasAttached = 0;409returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL);410} else if (returnValue == JNI_EVERSION) {411/* this version of JNI is not supported, so just try to attach */412/* we assume it was attached to ensure that this thread is not detached413* afterwards even though it should not414*/415wasAttached = 1;416returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL);417} else {418/* attached */419wasAttached = 1;420}421422jLockMutexClass = (*env)->FindClass(env, CLASS_LOCKMUTEX);423if (jLockMutexClass == NULL) { return rv; }424jInitArgsClass = (*env)->FindClass(env, CLASS_C_INITIALIZE_ARGS);425if (jInitArgsClass == NULL) { return rv; }426427/* convert the CK mutex to a Java mutex */428jMutex = ckVoidPtrToJObject(pMutex);429430/* get the LockMutex object out of the jInitArgs object */431fieldID = (*env)->GetFieldID(env, jInitArgsClass, "LockMutex", "Lsun/security/pkcs11/wrapper/CK_LOCKMUTEX;");432if (fieldID == NULL) { return rv; }433jLockMutex = (*env)->GetObjectField(env, jInitArgsObject, fieldID);434assert(jLockMutex != 0);435436/* call the CK_LOCKMUTEX method of the LockMutex object */437methodID = (*env)->GetMethodID(env, jLockMutexClass, "CK_LOCKMUTEX", "(Ljava/lang/Object;)V");438if (methodID == NULL) { return rv; }439(*env)->CallVoidMethod(env, jLockMutex, methodID, jMutex);440441/* check, if callback threw an exception */442pkcs11Exception = (*env)->ExceptionOccurred(env);443444if (pkcs11Exception != NULL) {445/* TBD: clear the pending exception with ExceptionClear? */446/* The was an exception thrown, now we get the error-code from it */447pkcs11ExceptionClass = (*env)->FindClass(env, CLASS_PKCS11EXCEPTION);448if (pkcs11ExceptionClass == NULL) { return rv; }449methodID = (*env)->GetMethodID(env, pkcs11ExceptionClass, "getErrorCode", "()J");450if (methodID == NULL) { return rv; }451errorCode = (*env)->CallLongMethod(env, pkcs11Exception, methodID);452rv = jLongToCKULong(errorCode);453}454455/* if we attached this thread to the VM just for callback, we detach it now */456if (wasAttached) {457returnValue = (*jvm)->DetachCurrentThread(jvm);458}459460return rv ;461}462463/*464* is the function that gets called by PKCS#11 to unlock a mutex and calls the Java465* UnlockMutex function466*467* @param env - used to call JNI funktions to get the Java classes, objects, methods and fields468* @param pMutex - the mutex to unlock469* @return - should return CKR_OK if the mutex was not unlocked already470*/471CK_RV callJUnlockMutex(CK_VOID_PTR pMutex)472{473extern JavaVM *jvm;474JNIEnv *env;475jint returnValue;476jthrowable pkcs11Exception;477jclass pkcs11ExceptionClass;478jlong errorCode;479CK_RV rv = CKR_OK;480int wasAttached = 1;481jclass jUnlockMutexClass;482jclass jInitArgsClass;483jmethodID methodID;484jfieldID fieldID;485jobject jUnlockMutex;486jobject jMutex;487488489/* Get the currently running Java VM */490if (jvm == NULL) { return rv ; } /* there is no VM running */491492/* Determine, if current thread is already attached */493returnValue = (*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION_1_2);494if (returnValue == JNI_EDETACHED) {495/* thread detached, so attach it */496wasAttached = 0;497returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL);498} else if (returnValue == JNI_EVERSION) {499/* this version of JNI is not supported, so just try to attach */500/* we assume it was attached to ensure that this thread is not detached501* afterwards even though it should not502*/503wasAttached = 1;504returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL);505} else {506/* attached */507wasAttached = 1;508}509510jUnlockMutexClass = (*env)->FindClass(env, CLASS_UNLOCKMUTEX);511if (jUnlockMutexClass == NULL) { return rv; }512jInitArgsClass = (*env)->FindClass(env, CLASS_C_INITIALIZE_ARGS);513if (jInitArgsClass == NULL) { return rv; }514515/* convert the CK-type mutex to a Java mutex */516jMutex = ckVoidPtrToJObject(pMutex);517518/* get the UnlockMutex object out of the jInitArgs object */519fieldID = (*env)->GetFieldID(env, jInitArgsClass, "UnlockMutex", "Lsun/security/pkcs11/wrapper/CK_UNLOCKMUTEX;");520if (fieldID == NULL) { return rv; }521jUnlockMutex = (*env)->GetObjectField(env, jInitArgsObject, fieldID);522assert(jUnlockMutex != 0);523524/* call the CK_UNLOCKMUTEX method of the UnLockMutex object */525methodID = (*env)->GetMethodID(env, jUnlockMutexClass, "CK_UNLOCKMUTEX", "(Ljava/lang/Object;)V");526if (methodID == NULL) { return rv; }527(*env)->CallVoidMethod(env, jUnlockMutex, methodID, jMutex);528529/* check, if callback threw an exception */530pkcs11Exception = (*env)->ExceptionOccurred(env);531532if (pkcs11Exception != NULL) {533/* TBD: clear the pending exception with ExceptionClear? */534/* The was an exception thrown, now we get the error-code from it */535pkcs11ExceptionClass = (*env)->FindClass(env, CLASS_PKCS11EXCEPTION);536if (pkcs11ExceptionClass == NULL) { return rv; }537methodID = (*env)->GetMethodID(env, pkcs11ExceptionClass, "getErrorCode", "()J");538if (methodID == NULL) { return rv; }539errorCode = (*env)->CallLongMethod(env, pkcs11Exception, methodID);540rv = jLongToCKULong(errorCode);541}542543/* if we attached this thread to the VM just for callback, we detach it now */544if (wasAttached) {545returnValue = (*jvm)->DetachCurrentThread(jvm);546}547548return rv ;549}550551#endif /* NO_CALLBACKS */552553554