1 /*
   2  * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 
   5 /* Copyright  (c) 2002 Graz University of Technology. All rights reserved.
   6  *
   7  * Redistribution and use in  source and binary forms, with or without
   8  * modification, are permitted  provided that the following conditions are met:
   9  *
  10  * 1. Redistributions of  source code must retain the above copyright notice,
  11  *    this list of conditions and the following disclaimer.
  12  *
  13  * 2. Redistributions in  binary form must reproduce the above copyright notice,
  14  *    this list of conditions and the following disclaimer in the documentation
  15  *    and/or other materials provided with the distribution.
  16  *
  17  * 3. The end-user documentation included with the redistribution, if any, must
  18  *    include the following acknowledgment:
  19  *
  20  *    "This product includes software developed by IAIK of Graz University of
  21  *     Technology."
  22  *
  23  *    Alternately, this acknowledgment may appear in the software itself, if
  24  *    and wherever such third-party acknowledgments normally appear.
  25  *
  26  * 4. The names "Graz University of Technology" and "IAIK of Graz University of
  27  *    Technology" must not be used to endorse or promote products derived from
  28  *    this software without prior written permission.
  29  *
  30  * 5. Products derived from this software may not be called
  31  *    "IAIK PKCS Wrapper", nor may "IAIK" appear in their name, without prior
  32  *    written permission of Graz University of Technology.
  33  *
  34  *  THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
  35  *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  36  *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  37  *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
  38  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
  39  *  OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  40  *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
  41  *  OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  42  *  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  43  *  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  44  *  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  45  *  POSSIBILITY  OF SUCH DAMAGE.
  46  */
  47 
  48 #include "pkcs11wrapper.h"
  49 
  50 #include <stdio.h>
  51 #include <stdlib.h>
  52 #include <string.h>
  53 #include <assert.h>
  54 
  55 /* declare file private functions */
  56 
  57 ModuleData * getModuleEntry(JNIEnv *env, jobject pkcs11Implementation);
  58 int isModulePresent(JNIEnv *env, jobject pkcs11Implementation);
  59 void removeAllModuleEntries(JNIEnv *env);
  60 
  61 
  62 /* ************************************************************************** */
  63 /* Functions for keeping track of currently active and loaded modules         */
  64 /* ************************************************************************** */
  65 
  66 
  67 /*
  68  * Create a new object for locking.
  69  */
  70 jobject createLockObject(JNIEnv *env) {
  71     jclass jObjectClass;
  72     jobject jLockObject;
  73     jmethodID jConstructor;
  74 
  75     jObjectClass = (*env)->FindClass(env, "java/lang/Object");
  76     if (jObjectClass == NULL) { return NULL; }
  77     jConstructor = (*env)->GetMethodID(env, jObjectClass, "<init>", "()V");
  78     if (jConstructor == NULL) { return NULL; }
  79     jLockObject = (*env)->NewObject(env, jObjectClass, jConstructor);
  80     if (jLockObject == NULL) { return NULL; }
  81     jLockObject = (*env)->NewGlobalRef(env, jLockObject);
  82 
  83     return jLockObject ;
  84 }
  85 
  86 /*
  87  * Create a new object for locking.
  88  */
  89 void destroyLockObject(JNIEnv *env, jobject jLockObject) {
  90     if (jLockObject != NULL) {
  91         (*env)->DeleteGlobalRef(env, jLockObject);
  92     }
  93 }
  94 
  95 /*
  96  * Add the given pkcs11Implementation object to the list of present modules.
  97  * Attach the given data to the entry. If the given pkcs11Implementation is
  98  * already in the lsit, just override its old module data with the new one.
  99  * None of the arguments can be NULL. If one of the arguments is NULL, this
 100  * function does nothing.
 101  */
 102 void putModuleEntry(JNIEnv *env, jobject pkcs11Implementation, ModuleData *moduleData) {
 103     if (pkcs11Implementation == NULL_PTR) {
 104         return ;
 105     }
 106     if (moduleData == NULL) {
 107         return ;
 108     }
 109     (*env)->SetLongField(env, pkcs11Implementation, pNativeDataID, ptr_to_jlong(moduleData));
 110 }
 111 
 112 
 113 /*
 114  * Get the module data of the entry for the given pkcs11Implementation. Returns
 115  * NULL, if the pkcs11Implementation is not in the list.
 116  */
 117 ModuleData * getModuleEntry(JNIEnv *env, jobject pkcs11Implementation) {
 118     jlong jData;
 119     if (pkcs11Implementation == NULL) {
 120         return NULL;
 121     }
 122     jData = (*env)->GetLongField(env, pkcs11Implementation, pNativeDataID);
 123     return (ModuleData*)jlong_to_ptr(jData);
 124 }
 125 
 126 CK_FUNCTION_LIST_PTR getFunctionList(JNIEnv *env, jobject pkcs11Implementation) {
 127     ModuleData *moduleData;
 128     CK_FUNCTION_LIST_PTR ckpFunctions;
 129 
 130     moduleData = getModuleEntry(env, pkcs11Implementation);
 131     if (moduleData == NULL) {
 132         throwDisconnectedRuntimeException(env);
 133         return NULL;
 134     }
 135     ckpFunctions = moduleData->ckFunctionListPtr;
 136     return ckpFunctions;
 137 }
 138 
 139 
 140 /*
 141  * Returns 1, if the given pkcs11Implementation is in the list.
 142  * 0, otherwise.
 143  */
 144 int isModulePresent(JNIEnv *env, jobject pkcs11Implementation) {
 145     int present;
 146 
 147     ModuleData *moduleData = getModuleEntry(env, pkcs11Implementation);
 148 
 149     present = (moduleData != NULL) ? 1 : 0;
 150 
 151     return present ;
 152 }
 153 
 154 
 155 /*
 156  * Removes the entry for the given pkcs11Implementation from the list. Returns
 157  * the module's data, after the node was removed. If this function returns NULL
 158  * the pkcs11Implementation was not in the list.
 159  */
 160 ModuleData * removeModuleEntry(JNIEnv *env, jobject pkcs11Implementation) {
 161     ModuleData *moduleData = getModuleEntry(env, pkcs11Implementation);
 162     if (moduleData == NULL) {
 163         return NULL;
 164     }
 165     (*env)->SetLongField(env, pkcs11Implementation, pNativeDataID, 0);
 166     return moduleData;
 167 }
 168 
 169 /*
 170  * Removes all present entries from the list of modules and frees all
 171  * associated resources. This function is used for clean-up.
 172  */
 173 void removeAllModuleEntries(JNIEnv *env) {
 174     /* XXX empty */
 175 }
 176 
 177 /* ************************************************************************** */
 178 /* Below there follow the helper functions to support conversions between     */
 179 /* Java and Cryptoki types                                                    */
 180 /* ************************************************************************** */
 181 
 182 /*
 183  * function to convert a PKCS#11 return value into a PKCS#11Exception
 184  *
 185  * This function generates a PKCS#11Exception with the returnValue as the errorcode
 186  * if the returnValue is not CKR_OK. The functin returns 0, if the returnValue is
 187  * CKR_OK. Otherwise, it returns the returnValue as a jLong.
 188  *
 189  * @param env - used to call JNI funktions and to get the Exception class
 190  * @param returnValue - of the PKCS#11 function
 191  */
 192 jlong ckAssertReturnValueOK(JNIEnv *env, CK_RV returnValue)
 193 {
 194     jclass jPKCS11ExceptionClass;
 195     jmethodID jConstructor;
 196     jthrowable jPKCS11Exception;
 197     jlong jErrorCode = 0L;
 198 
 199     if (returnValue != CKR_OK) {
 200         jErrorCode = ckULongToJLong(returnValue);
 201         jPKCS11ExceptionClass = (*env)->FindClass(env, CLASS_PKCS11EXCEPTION);
 202         if (jPKCS11ExceptionClass != NULL) {
 203             jConstructor = (*env)->GetMethodID(env, jPKCS11ExceptionClass, "<init>", "(J)V");
 204             if (jConstructor != NULL) {
 205                 jPKCS11Exception = (jthrowable) (*env)->NewObject(env, jPKCS11ExceptionClass, jConstructor, jErrorCode);
 206                 if (jPKCS11Exception != NULL) {
 207                     (*env)->Throw(env, jPKCS11Exception);
 208                 }
 209             }
 210         }
 211         (*env)->DeleteLocalRef(env, jPKCS11ExceptionClass);
 212     }
 213     return jErrorCode ;
 214 }
 215 
 216 
 217 /*
 218  * Throws a Java Exception by name
 219  */
 220 void throwByName(JNIEnv *env, const char *name, const char *msg)
 221 {
 222     jclass cls = (*env)->FindClass(env, name);
 223 
 224     if (cls != 0) /* Otherwise an exception has already been thrown */
 225         (*env)->ThrowNew(env, cls, msg);
 226 }
 227 
 228 /*
 229  * Throws java.lang.OutOfMemoryError
 230  */
 231 void throwOutOfMemoryError(JNIEnv *env, const char *msg)
 232 {
 233     throwByName(env, "java/lang/OutOfMemoryError", msg);
 234 }
 235 
 236 /*
 237  * Throws java.lang.NullPointerException
 238  */
 239 void throwNullPointerException(JNIEnv *env, const char *msg)
 240 {
 241     throwByName(env, "java/lang/NullPointerException", msg);
 242 }
 243 
 244 /*
 245  * Throws java.io.IOException
 246  */
 247 void throwIOException(JNIEnv *env, const char *msg)
 248 {
 249     throwByName(env, "java/io/IOException", msg);
 250 }
 251 
 252 /*
 253  * This function simply throws a PKCS#11RuntimeException with the given
 254  * string as its message.
 255  *
 256  * @param env Used to call JNI funktions and to get the Exception class.
 257  * @param jmessage The message string of the Exception object.
 258  */
 259 void throwPKCS11RuntimeException(JNIEnv *env, const char *message)
 260 {
 261     throwByName(env, CLASS_PKCS11RUNTIMEEXCEPTION, message);
 262 }
 263 
 264 /*
 265  * This function simply throws a PKCS#11RuntimeException. The message says that
 266  * the object is not connected to the module.
 267  *
 268  * @param env Used to call JNI funktions and to get the Exception class.
 269  */
 270 void throwDisconnectedRuntimeException(JNIEnv *env)
 271 {
 272     throwPKCS11RuntimeException(env, "This object is not connected to a module.");
 273 }
 274 
 275 /* This function frees the specified CK_ATTRIBUTE array.
 276  *
 277  * @param attrPtr pointer to the to-be-freed CK_ATTRIBUTE array.
 278  * @param len the length of the array
 279  */
 280 void freeCKAttributeArray(CK_ATTRIBUTE_PTR attrPtr, int len)
 281 {
 282     int i;
 283 
 284     for (i=0; i<len; i++) {
 285         if (attrPtr[i].pValue != NULL_PTR) {
 286             free(attrPtr[i].pValue);
 287         }
 288     }
 289     free(attrPtr);
 290 }
 291 
 292 /*
 293  * the following functions convert Java arrays to PKCS#11 array pointers and
 294  * their array length and vice versa
 295  *
 296  * void j<Type>ArrayToCK<Type>Array(JNIEnv *env,
 297  *                                  const j<Type>Array jArray,
 298  *                                  CK_<Type>_PTR *ckpArray,
 299  *                                  CK_ULONG_PTR ckLength);
 300  *
 301  * j<Type>Array ck<Type>ArrayToJ<Type>Array(JNIEnv *env,
 302  *                                          const CK_<Type>_PTR ckpArray,
 303  *                                          CK_ULONG ckLength);
 304  *
 305  * PKCS#11 arrays consist always of a pointer to the beginning of the array and
 306  * the array length whereas Java arrays carry their array length.
 307  *
 308  * The Functions to convert a Java array to a PKCS#11 array are void functions.
 309  * Their arguments are the Java array object to convert, the reference to the
 310  * array pointer, where the new PKCS#11 array should be stored and the reference
 311  * to the array length where the PKCS#11 array length should be stored. These two
 312  * references must not be NULL_PTR.
 313  *
 314  * The functions first obtain the array length of the Java array and then allocate
 315  * the memory for the PKCS#11 array and set the array length. Then each element
 316  * gets converted depending on their type. After use the allocated memory of the
 317  * PKCS#11 array has to be explicitly freed.
 318  *
 319  * The Functions to convert a PKCS#11 array to a Java array get the PKCS#11 array
 320  * pointer and the array length and they return the new Java array object. The
 321  * Java array does not need to get freed after use.
 322  */
 323 
 324 /*
 325  * converts a jbooleanArray to a CK_BBOOL array. The allocated memory has to be freed after use!
 326  *
 327  * @param env - used to call JNI funktions to get the array informtaion
 328  * @param jArray - the Java array to convert
 329  * @param ckpArray - the reference, where the pointer to the new CK_BBOOL array will be stored
 330  * @param ckpLength - the reference, where the array length will be stored
 331  */
 332 void jBooleanArrayToCKBBoolArray(JNIEnv *env, const jbooleanArray jArray, CK_BBOOL **ckpArray, CK_ULONG_PTR ckpLength)
 333 {
 334     jboolean* jpTemp;
 335     CK_ULONG i;
 336 
 337     if(jArray == NULL) {
 338         *ckpArray = NULL_PTR;
 339         *ckpLength = 0L;
 340         return;
 341     }
 342     *ckpLength = (*env)->GetArrayLength(env, jArray);
 343     jpTemp = (jboolean*) malloc((*ckpLength) * sizeof(jboolean));
 344     if (jpTemp == NULL) {
 345         throwOutOfMemoryError(env, 0);
 346         return;
 347     }
 348     (*env)->GetBooleanArrayRegion(env, jArray, 0, *ckpLength, jpTemp);
 349     if ((*env)->ExceptionCheck(env)) {
 350         free(jpTemp);
 351         return;
 352     }
 353 
 354     *ckpArray = (CK_BBOOL*) malloc ((*ckpLength) * sizeof(CK_BBOOL));
 355     if (*ckpArray == NULL) {
 356         free(jpTemp);
 357         throwOutOfMemoryError(env, 0);
 358         return;
 359     }
 360     for (i=0; i<(*ckpLength); i++) {
 361         (*ckpArray)[i] = jBooleanToCKBBool(jpTemp[i]);
 362     }
 363     free(jpTemp);
 364 }
 365 
 366 /*
 367  * converts a jbyteArray to a CK_BYTE array. The allocated memory has to be freed after use!
 368  *
 369  * @param env - used to call JNI funktions to get the array informtaion
 370  * @param jArray - the Java array to convert
 371  * @param ckpArray - the reference, where the pointer to the new CK_BYTE array will be stored
 372  * @param ckpLength - the reference, where the array length will be stored
 373  */
 374 void jByteArrayToCKByteArray(JNIEnv *env, const jbyteArray jArray, CK_BYTE_PTR *ckpArray, CK_ULONG_PTR ckpLength)
 375 {
 376     jbyte* jpTemp;
 377     CK_ULONG i;
 378 
 379     if(jArray == NULL) {
 380         *ckpArray = NULL_PTR;
 381         *ckpLength = 0L;
 382         return;
 383     }
 384     *ckpLength = (*env)->GetArrayLength(env, jArray);
 385     jpTemp = (jbyte*) malloc((*ckpLength) * sizeof(jbyte));
 386     if (jpTemp == NULL) {
 387         throwOutOfMemoryError(env, 0);
 388         return;
 389     }
 390     (*env)->GetByteArrayRegion(env, jArray, 0, *ckpLength, jpTemp);
 391     if ((*env)->ExceptionCheck(env)) {
 392         free(jpTemp);
 393         return;
 394     }
 395 
 396     /* if CK_BYTE is the same size as jbyte, we save an additional copy */
 397     if (sizeof(CK_BYTE) == sizeof(jbyte)) {
 398         *ckpArray = (CK_BYTE_PTR) jpTemp;
 399     } else {
 400         *ckpArray = (CK_BYTE_PTR) malloc ((*ckpLength) * sizeof(CK_BYTE));
 401         if (*ckpArray == NULL) {
 402             free(jpTemp);
 403             throwOutOfMemoryError(env, 0);
 404             return;
 405         }
 406         for (i=0; i<(*ckpLength); i++) {
 407             (*ckpArray)[i] = jByteToCKByte(jpTemp[i]);
 408         }
 409         free(jpTemp);
 410     }
 411 }
 412 
 413 /*
 414  * converts a jlongArray to a CK_ULONG array. The allocated memory has to be freed after use!
 415  *
 416  * @param env - used to call JNI funktions to get the array informtaion
 417  * @param jArray - the Java array to convert
 418  * @param ckpArray - the reference, where the pointer to the new CK_ULONG array will be stored
 419  * @param ckpLength - the reference, where the array length will be stored
 420  */
 421 void jLongArrayToCKULongArray(JNIEnv *env, const jlongArray jArray, CK_ULONG_PTR *ckpArray, CK_ULONG_PTR ckpLength)
 422 {
 423     jlong* jTemp;
 424     CK_ULONG i;
 425 
 426     if(jArray == NULL) {
 427         *ckpArray = NULL_PTR;
 428         *ckpLength = 0L;
 429         return;
 430     }
 431     *ckpLength = (*env)->GetArrayLength(env, jArray);
 432     jTemp = (jlong*) malloc((*ckpLength) * sizeof(jlong));
 433     if (jTemp == NULL) {
 434         throwOutOfMemoryError(env, 0);
 435         return;
 436     }
 437     (*env)->GetLongArrayRegion(env, jArray, 0, *ckpLength, jTemp);
 438     if ((*env)->ExceptionCheck(env)) {
 439         free(jTemp);
 440         return;
 441     }
 442 
 443     *ckpArray = (CK_ULONG_PTR) malloc (*ckpLength * sizeof(CK_ULONG));
 444     if (*ckpArray == NULL) {
 445         free(jTemp);
 446         throwOutOfMemoryError(env, 0);
 447         return;
 448     }
 449     for (i=0; i<(*ckpLength); i++) {
 450         (*ckpArray)[i] = jLongToCKULong(jTemp[i]);
 451     }
 452     free(jTemp);
 453 }
 454 
 455 /*
 456  * converts a jcharArray to a CK_CHAR array. The allocated memory has to be freed after use!
 457  *
 458  * @param env - used to call JNI funktions to get the array informtaion
 459  * @param jArray - the Java array to convert
 460  * @param ckpArray - the reference, where the pointer to the new CK_CHAR array will be stored
 461  * @param ckpLength - the reference, where the array length will be stored
 462  */
 463 void jCharArrayToCKCharArray(JNIEnv *env, const jcharArray jArray, CK_CHAR_PTR *ckpArray, CK_ULONG_PTR ckpLength)
 464 {
 465     jchar* jpTemp;
 466     CK_ULONG i;
 467 
 468     if(jArray == NULL) {
 469         *ckpArray = NULL_PTR;
 470         *ckpLength = 0L;
 471         return;
 472     }
 473     *ckpLength = (*env)->GetArrayLength(env, jArray);
 474     jpTemp = (jchar*) malloc((*ckpLength) * sizeof(jchar));
 475     if (jpTemp == NULL) {
 476         throwOutOfMemoryError(env, 0);
 477         return;
 478     }
 479     (*env)->GetCharArrayRegion(env, jArray, 0, *ckpLength, jpTemp);
 480     if ((*env)->ExceptionCheck(env)) {
 481         free(jpTemp);
 482         return;
 483     }
 484 
 485     *ckpArray = (CK_CHAR_PTR) malloc (*ckpLength * sizeof(CK_CHAR));
 486     if (*ckpArray == NULL) {
 487         free(jpTemp);
 488         throwOutOfMemoryError(env, 0);
 489         return;
 490     }
 491     for (i=0; i<(*ckpLength); i++) {
 492         (*ckpArray)[i] = jCharToCKChar(jpTemp[i]);
 493     }
 494     free(jpTemp);
 495 }
 496 
 497 /*
 498  * converts a jcharArray to a CK_UTF8CHAR array. The allocated memory has to be freed after use!
 499  *
 500  * @param env - used to call JNI funktions to get the array informtaion
 501  * @param jArray - the Java array to convert
 502  * @param ckpArray - the reference, where the pointer to the new CK_UTF8CHAR array will be stored
 503  * @param ckpLength - the reference, where the array length will be stored
 504  */
 505 void jCharArrayToCKUTF8CharArray(JNIEnv *env, const jcharArray jArray, CK_UTF8CHAR_PTR *ckpArray, CK_ULONG_PTR ckpLength)
 506 {
 507     jchar* jTemp;
 508     CK_ULONG i;
 509 
 510     if(jArray == NULL) {
 511         *ckpArray = NULL_PTR;
 512         *ckpLength = 0L;
 513         return;
 514     }
 515     *ckpLength = (*env)->GetArrayLength(env, jArray);
 516     jTemp = (jchar*) malloc((*ckpLength) * sizeof(jchar));
 517     if (jTemp == NULL) {
 518         throwOutOfMemoryError(env, 0);
 519         return;
 520     }
 521     (*env)->GetCharArrayRegion(env, jArray, 0, *ckpLength, jTemp);
 522     if ((*env)->ExceptionCheck(env)) {
 523         free(jTemp);
 524         return;
 525     }
 526 
 527     *ckpArray = (CK_UTF8CHAR_PTR) malloc (*ckpLength * sizeof(CK_UTF8CHAR));
 528     if (*ckpArray == NULL) {
 529         free(jTemp);
 530         throwOutOfMemoryError(env, 0);
 531         return;
 532     }
 533     for (i=0; i<(*ckpLength); i++) {
 534         (*ckpArray)[i] = jCharToCKUTF8Char(jTemp[i]);
 535     }
 536     free(jTemp);
 537 }
 538 
 539 /*
 540  * converts a jstring to a CK_CHAR array. The allocated memory has to be freed after use!
 541  *
 542  * @param env - used to call JNI funktions to get the array informtaion
 543  * @param jArray - the Java array to convert
 544  * @param ckpArray - the reference, where the pointer to the new CK_CHAR array will be stored
 545  * @param ckpLength - the reference, where the array length will be stored
 546  */
 547 void jStringToCKUTF8CharArray(JNIEnv *env, const jstring jArray, CK_UTF8CHAR_PTR *ckpArray, CK_ULONG_PTR ckpLength)
 548 {
 549     const char* pCharArray;
 550     jboolean isCopy;
 551 
 552     if(jArray == NULL) {
 553         *ckpArray = NULL_PTR;
 554         *ckpLength = 0L;
 555         return;
 556     }
 557 
 558     pCharArray = (*env)->GetStringUTFChars(env, jArray, &isCopy);
 559     if (pCharArray == NULL) { return; }
 560 
 561     *ckpLength = (CK_ULONG) strlen(pCharArray);
 562     *ckpArray = (CK_UTF8CHAR_PTR) malloc((*ckpLength + 1) * sizeof(CK_UTF8CHAR));
 563     if (*ckpArray == NULL) {
 564         (*env)->ReleaseStringUTFChars(env, (jstring) jArray, pCharArray);
 565         throwOutOfMemoryError(env, 0);
 566         return;
 567     }
 568     strcpy((char*)*ckpArray, pCharArray);
 569     (*env)->ReleaseStringUTFChars(env, (jstring) jArray, pCharArray);
 570 }
 571 
 572 /*
 573  * converts a jobjectArray with Java Attributes to a CK_ATTRIBUTE array. The allocated memory
 574  * has to be freed after use!
 575  *
 576  * @param env - used to call JNI funktions to get the array informtaion
 577  * @param jArray - the Java Attribute array (template) to convert
 578  * @param ckpArray - the reference, where the pointer to the new CK_ATTRIBUTE array will be
 579  *                   stored
 580  * @param ckpLength - the reference, where the array length will be stored
 581  */
 582 void jAttributeArrayToCKAttributeArray(JNIEnv *env, jobjectArray jArray, CK_ATTRIBUTE_PTR *ckpArray, CK_ULONG_PTR ckpLength)
 583 {
 584     CK_ULONG i;
 585     jlong jLength;
 586     jobject jAttribute;
 587 
 588     TRACE0("\nDEBUG: jAttributeArrayToCKAttributeArray");
 589     if (jArray == NULL) {
 590         *ckpArray = NULL_PTR;
 591         *ckpLength = 0L;
 592         return;
 593     }
 594     jLength = (*env)->GetArrayLength(env, jArray);
 595     *ckpLength = jLongToCKULong(jLength);
 596     *ckpArray = (CK_ATTRIBUTE_PTR) malloc(*ckpLength * sizeof(CK_ATTRIBUTE));
 597     if (*ckpArray == NULL) {
 598         throwOutOfMemoryError(env, 0);
 599         return;
 600     }
 601     TRACE1(", converting %d attributes", jLength);
 602     for (i=0; i<(*ckpLength); i++) {
 603         TRACE1(", getting %d. attribute", i);
 604         jAttribute = (*env)->GetObjectArrayElement(env, jArray, i);
 605         if ((*env)->ExceptionCheck(env)) {
 606             freeCKAttributeArray(*ckpArray, i);
 607             return;
 608         }
 609         TRACE1(", jAttribute = %d", jAttribute);
 610         TRACE1(", converting %d. attribute", i);
 611         (*ckpArray)[i] = jAttributeToCKAttribute(env, jAttribute);
 612         if ((*env)->ExceptionCheck(env)) {
 613             freeCKAttributeArray(*ckpArray, i);
 614             return;
 615         }
 616     }
 617     TRACE0("FINISHED\n");
 618 }
 619 
 620 /*
 621  * converts a CK_BYTE array and its length to a jbyteArray.
 622  *
 623  * @param env - used to call JNI funktions to create the new Java array
 624  * @param ckpArray - the pointer to the CK_BYTE array to convert
 625  * @param ckpLength - the length of the array to convert
 626  * @return - the new Java byte array or NULL if error occurred
 627  */
 628 jbyteArray ckByteArrayToJByteArray(JNIEnv *env, const CK_BYTE_PTR ckpArray, CK_ULONG ckLength)
 629 {
 630     CK_ULONG i;
 631     jbyte* jpTemp;
 632     jbyteArray jArray;
 633 
 634     /* if CK_BYTE is the same size as jbyte, we save an additional copy */
 635     if (sizeof(CK_BYTE) == sizeof(jbyte)) {
 636         jpTemp = (jbyte*) ckpArray;
 637     } else {
 638         jpTemp = (jbyte*) malloc((ckLength) * sizeof(jbyte));
 639         if (jpTemp == NULL) {
 640             throwOutOfMemoryError(env, 0);
 641             return NULL;
 642         }
 643         for (i=0; i<ckLength; i++) {
 644             jpTemp[i] = ckByteToJByte(ckpArray[i]);
 645         }
 646     }
 647 
 648     jArray = (*env)->NewByteArray(env, ckULongToJSize(ckLength));
 649     if (jArray != NULL) {
 650         (*env)->SetByteArrayRegion(env, jArray, 0, ckULongToJSize(ckLength), jpTemp);
 651     }
 652 
 653     if (sizeof(CK_BYTE) != sizeof(jbyte)) { free(jpTemp); }
 654 
 655     return jArray ;
 656 }
 657 
 658 /*
 659  * converts a CK_ULONG array and its length to a jlongArray.
 660  *
 661  * @param env - used to call JNI funktions to create the new Java array
 662  * @param ckpArray - the pointer to the CK_ULONG array to convert
 663  * @param ckpLength - the length of the array to convert
 664  * @return - the new Java long array
 665  */
 666 jlongArray ckULongArrayToJLongArray(JNIEnv *env, const CK_ULONG_PTR ckpArray, CK_ULONG ckLength)
 667 {
 668     CK_ULONG i;
 669     jlong* jpTemp;
 670     jlongArray jArray;
 671 
 672     jpTemp = (jlong*) malloc((ckLength) * sizeof(jlong));
 673     if (jpTemp == NULL) {
 674         throwOutOfMemoryError(env, 0);
 675         return NULL;
 676     }
 677     for (i=0; i<ckLength; i++) {
 678         jpTemp[i] = ckLongToJLong(ckpArray[i]);
 679     }
 680     jArray = (*env)->NewLongArray(env, ckULongToJSize(ckLength));
 681     if (jArray != NULL) {
 682         (*env)->SetLongArrayRegion(env, jArray, 0, ckULongToJSize(ckLength), jpTemp);
 683     }
 684     free(jpTemp);
 685 
 686     return jArray ;
 687 }
 688 
 689 /*
 690  * converts a CK_CHAR array and its length to a jcharArray.
 691  *
 692  * @param env - used to call JNI funktions to create the new Java array
 693  * @param ckpArray - the pointer to the CK_CHAR array to convert
 694  * @param ckpLength - the length of the array to convert
 695  * @return - the new Java char array
 696  */
 697 jcharArray ckCharArrayToJCharArray(JNIEnv *env, const CK_CHAR_PTR ckpArray, CK_ULONG ckLength)
 698 {
 699     CK_ULONG i;
 700     jchar* jpTemp;
 701     jcharArray jArray;
 702 
 703     jpTemp = (jchar*) malloc(ckLength * sizeof(jchar));
 704     if (jpTemp == NULL) {
 705         throwOutOfMemoryError(env, 0);
 706         return NULL;
 707     }
 708     for (i=0; i<ckLength; i++) {
 709         jpTemp[i] = ckCharToJChar(ckpArray[i]);
 710     }
 711     jArray = (*env)->NewCharArray(env, ckULongToJSize(ckLength));
 712     if (jArray != NULL) {
 713         (*env)->SetCharArrayRegion(env, jArray, 0, ckULongToJSize(ckLength), jpTemp);
 714     }
 715     free(jpTemp);
 716 
 717     return jArray ;
 718 }
 719 
 720 /*
 721  * converts a CK_UTF8CHAR array and its length to a jcharArray.
 722  *
 723  * @param env - used to call JNI funktions to create the new Java array
 724  * @param ckpArray - the pointer to the CK_UTF8CHAR array to convert
 725  * @param ckpLength - the length of the array to convert
 726  * @return - the new Java char array
 727  */
 728 jcharArray ckUTF8CharArrayToJCharArray(JNIEnv *env, const CK_UTF8CHAR_PTR ckpArray, CK_ULONG ckLength)
 729 {
 730     CK_ULONG i;
 731     jchar* jpTemp;
 732     jcharArray jArray;
 733 
 734     jpTemp = (jchar*) malloc(ckLength * sizeof(jchar));
 735     if (jpTemp == NULL) {
 736         throwOutOfMemoryError(env, 0);
 737         return NULL;
 738     }
 739     for (i=0; i<ckLength; i++) {
 740         jpTemp[i] = ckUTF8CharToJChar(ckpArray[i]);
 741     }
 742     jArray = (*env)->NewCharArray(env, ckULongToJSize(ckLength));
 743     if (jArray != NULL) {
 744         (*env)->SetCharArrayRegion(env, jArray, 0, ckULongToJSize(ckLength), jpTemp);
 745     }
 746     free(jpTemp);
 747 
 748     return jArray ;
 749 }
 750 
 751 /*
 752  * the following functions convert Java objects to PKCS#11 pointers and the
 753  * length in bytes and vice versa
 754  *
 755  * CK_<Type>_PTR j<Object>ToCK<Type>Ptr(JNIEnv *env, jobject jObject);
 756  *
 757  * jobject ck<Type>PtrToJ<Object>(JNIEnv *env, const CK_<Type>_PTR ckpValue);
 758  *
 759  * The functions that convert a Java object to a PKCS#11 pointer first allocate
 760  * the memory for the PKCS#11 pointer. Then they set each element corresponding
 761  * to the fields in the Java object to convert. After use the allocated memory of
 762  * the PKCS#11 pointer has to be explicitly freed.
 763  *
 764  * The functions to convert a PKCS#11 pointer to a Java object create a new Java
 765  * object first and than they set all fields in the object depending on the values
 766  * of the type or structure where the PKCS#11 pointer points to.
 767  */
 768 
 769 /*
 770  * converts a CK_BBOOL pointer to a Java boolean Object.
 771  *
 772  * @param env - used to call JNI funktions to create the new Java object
 773  * @param ckpValue - the pointer to the CK_BBOOL value
 774  * @return - the new Java boolean object with the boolean value
 775  */
 776 jobject ckBBoolPtrToJBooleanObject(JNIEnv *env, const CK_BBOOL *ckpValue)
 777 {
 778     jclass jValueObjectClass;
 779     jmethodID jConstructor;
 780     jobject jValueObject;
 781     jboolean jValue;
 782 
 783     jValueObjectClass = (*env)->FindClass(env, "java/lang/Boolean");
 784     if (jValueObjectClass == NULL) { return NULL; }
 785     jConstructor = (*env)->GetMethodID(env, jValueObjectClass, "<init>", "(Z)V");
 786     if (jConstructor == NULL) { return NULL; }
 787     jValue = ckBBoolToJBoolean(*ckpValue);
 788     jValueObject = (*env)->NewObject(env, jValueObjectClass, jConstructor, jValue);
 789 
 790     return jValueObject ;
 791 }
 792 
 793 /*
 794  * converts a CK_ULONG pointer to a Java long Object.
 795  *
 796  * @param env - used to call JNI funktions to create the new Java object
 797  * @param ckpValue - the pointer to the CK_ULONG value
 798  * @return - the new Java long object with the long value
 799  */
 800 jobject ckULongPtrToJLongObject(JNIEnv *env, const CK_ULONG_PTR ckpValue)
 801 {
 802     jclass jValueObjectClass;
 803     jmethodID jConstructor;
 804     jobject jValueObject;
 805     jlong jValue;
 806 
 807     jValueObjectClass = (*env)->FindClass(env, "java/lang/Long");
 808     if (jValueObjectClass == NULL) { return NULL; }
 809     jConstructor = (*env)->GetMethodID(env, jValueObjectClass, "<init>", "(J)V");
 810     if (jConstructor == NULL) { return NULL; }
 811     jValue = ckULongToJLong(*ckpValue);
 812     jValueObject = (*env)->NewObject(env, jValueObjectClass, jConstructor, jValue);
 813 
 814     return jValueObject ;
 815 }
 816 
 817 /*
 818  * converts a Java boolean object into a pointer to a CK_BBOOL value. The memory has to be
 819  * freed after use!
 820  *
 821  * @param env - used to call JNI funktions to get the value out of the Java object
 822  * @param jObject - the "java/lang/Boolean" object to convert
 823  * @return - the pointer to the new CK_BBOOL value
 824  */
 825 CK_BBOOL* jBooleanObjectToCKBBoolPtr(JNIEnv *env, jobject jObject)
 826 {
 827     jclass jObjectClass;
 828     jmethodID jValueMethod;
 829     jboolean jValue;
 830     CK_BBOOL *ckpValue;
 831 
 832     jObjectClass = (*env)->FindClass(env, "java/lang/Boolean");
 833     if (jObjectClass == NULL) { return NULL; }
 834     jValueMethod = (*env)->GetMethodID(env, jObjectClass, "booleanValue", "()Z");
 835     if (jValueMethod == NULL) { return NULL; }
 836     jValue = (*env)->CallBooleanMethod(env, jObject, jValueMethod);
 837     ckpValue = (CK_BBOOL *) malloc(sizeof(CK_BBOOL));
 838     if (ckpValue == NULL) {
 839         throwOutOfMemoryError(env, 0);
 840         return NULL;
 841     }
 842     *ckpValue = jBooleanToCKBBool(jValue);
 843 
 844     return ckpValue ;
 845 }
 846 
 847 /*
 848  * converts a Java byte object into a pointer to a CK_BYTE value. The memory has to be
 849  * freed after use!
 850  *
 851  * @param env - used to call JNI funktions to get the value out of the Java object
 852  * @param jObject - the "java/lang/Byte" object to convert
 853  * @return - the pointer to the new CK_BYTE value
 854  */
 855 CK_BYTE_PTR jByteObjectToCKBytePtr(JNIEnv *env, jobject jObject)
 856 {
 857     jclass jObjectClass;
 858     jmethodID jValueMethod;
 859     jbyte jValue;
 860     CK_BYTE_PTR ckpValue;
 861 
 862     jObjectClass = (*env)->FindClass(env, "java/lang/Byte");
 863     if (jObjectClass == NULL) { return NULL; }
 864     jValueMethod = (*env)->GetMethodID(env, jObjectClass, "byteValue", "()B");
 865     if (jValueMethod == NULL) { return NULL; }
 866     jValue = (*env)->CallByteMethod(env, jObject, jValueMethod);
 867     ckpValue = (CK_BYTE_PTR) malloc(sizeof(CK_BYTE));
 868     if (ckpValue == NULL) {
 869         throwOutOfMemoryError(env, 0);
 870         return NULL;
 871     }
 872     *ckpValue = jByteToCKByte(jValue);
 873     return ckpValue ;
 874 }
 875 
 876 /*
 877  * converts a Java integer object into a pointer to a CK_ULONG value. The memory has to be
 878  * freed after use!
 879  *
 880  * @param env - used to call JNI funktions to get the value out of the Java object
 881  * @param jObject - the "java/lang/Integer" object to convert
 882  * @return - the pointer to the new CK_ULONG value
 883  */
 884 CK_ULONG* jIntegerObjectToCKULongPtr(JNIEnv *env, jobject jObject)
 885 {
 886     jclass jObjectClass;
 887     jmethodID jValueMethod;
 888     jint jValue;
 889     CK_ULONG *ckpValue;
 890 
 891     jObjectClass = (*env)->FindClass(env, "java/lang/Integer");
 892     if (jObjectClass == NULL) { return NULL; }
 893     jValueMethod = (*env)->GetMethodID(env, jObjectClass, "intValue", "()I");
 894     if (jValueMethod == NULL) { return NULL; }
 895     jValue = (*env)->CallIntMethod(env, jObject, jValueMethod);
 896     ckpValue = (CK_ULONG *) malloc(sizeof(CK_ULONG));
 897     if (ckpValue == NULL) {
 898         throwOutOfMemoryError(env, 0);
 899         return NULL;
 900     }
 901     *ckpValue = jLongToCKLong(jValue);
 902     return ckpValue ;
 903 }
 904 
 905 /*
 906  * converts a Java long object into a pointer to a CK_ULONG value. The memory has to be
 907  * freed after use!
 908  *
 909  * @param env - used to call JNI funktions to get the value out of the Java object
 910  * @param jObject - the "java/lang/Long" object to convert
 911  * @return - the pointer to the new CK_ULONG value
 912  */
 913 CK_ULONG* jLongObjectToCKULongPtr(JNIEnv *env, jobject jObject)
 914 {
 915     jclass jObjectClass;
 916     jmethodID jValueMethod;
 917     jlong jValue;
 918     CK_ULONG *ckpValue;
 919 
 920     jObjectClass = (*env)->FindClass(env, "java/lang/Long");
 921     if (jObjectClass == NULL) { return NULL; }
 922     jValueMethod = (*env)->GetMethodID(env, jObjectClass, "longValue", "()J");
 923     if (jValueMethod == NULL) { return NULL; }
 924     jValue = (*env)->CallLongMethod(env, jObject, jValueMethod);
 925     ckpValue = (CK_ULONG *) malloc(sizeof(CK_ULONG));
 926     if (ckpValue == NULL) {
 927         throwOutOfMemoryError(env, 0);
 928         return NULL;
 929     }
 930     *ckpValue = jLongToCKULong(jValue);
 931 
 932     return ckpValue ;
 933 }
 934 
 935 /*
 936  * converts a Java char object into a pointer to a CK_CHAR value. The memory has to be
 937  * freed after use!
 938  *
 939  * @param env - used to call JNI funktions to get the value out of the Java object
 940  * @param jObject - the "java/lang/Char" object to convert
 941  * @return - the pointer to the new CK_CHAR value
 942  */
 943 CK_CHAR_PTR jCharObjectToCKCharPtr(JNIEnv *env, jobject jObject)
 944 {
 945     jclass jObjectClass;
 946     jmethodID jValueMethod;
 947     jchar jValue;
 948     CK_CHAR_PTR ckpValue;
 949 
 950     jObjectClass = (*env)->FindClass(env, "java/lang/Char");
 951     if (jObjectClass == NULL) { return NULL; }
 952     jValueMethod = (*env)->GetMethodID(env, jObjectClass, "charValue", "()C");
 953     if (jValueMethod == NULL) { return NULL; }
 954     jValue = (*env)->CallCharMethod(env, jObject, jValueMethod);
 955     ckpValue = (CK_CHAR_PTR) malloc(sizeof(CK_CHAR));
 956     if (ckpValue == NULL) {
 957         throwOutOfMemoryError(env, 0);
 958         return NULL;
 959     }
 960     *ckpValue = jCharToCKChar(jValue);
 961 
 962     return ckpValue ;
 963 }
 964 
 965 /*
 966  * converts a Java object into a pointer to CK-type or a CK-structure with the length in Bytes.
 967  * The memory of *ckpObjectPtr to be freed after use! This function is only used by
 968  * jAttributeToCKAttribute by now.
 969  *
 970  * @param env - used to call JNI funktions to get the Java classes and objects
 971  * @param jObject - the Java object to convert
 972  * @param ckpObjectPtr - the reference of the new pointer to the new CK-value or CK-structure
 973  * @param ckpLength - the reference of the length in bytes of the new CK-value or CK-structure
 974  */
 975 void jObjectToPrimitiveCKObjectPtrPtr(JNIEnv *env, jobject jObject, CK_VOID_PTR *ckpObjectPtr, CK_ULONG *ckpLength)
 976 {
 977     jclass jLongClass, jBooleanClass, jByteArrayClass, jCharArrayClass;
 978     jclass jByteClass, jDateClass, jCharacterClass, jIntegerClass;
 979     jclass jBooleanArrayClass, jIntArrayClass, jLongArrayClass;
 980     jclass jStringClass;
 981     jclass jObjectClass, jClassClass;
 982     CK_VOID_PTR ckpVoid = *ckpObjectPtr;
 983     jmethodID jMethod;
 984     jobject jClassObject;
 985     jstring jClassNameString;
 986     char *classNameString, *exceptionMsgPrefix, *exceptionMsg;
 987 
 988     TRACE0("\nDEBUG: jObjectToPrimitiveCKObjectPtrPtr");
 989     if (jObject == NULL) {
 990         *ckpObjectPtr = NULL;
 991         *ckpLength = 0;
 992         return;
 993     }
 994 
 995     jLongClass = (*env)->FindClass(env, "java/lang/Long");
 996     if (jLongClass == NULL) { return; }
 997     if ((*env)->IsInstanceOf(env, jObject, jLongClass)) {
 998         *ckpObjectPtr = jLongObjectToCKULongPtr(env, jObject);
 999         *ckpLength = sizeof(CK_ULONG);
1000         TRACE1("<converted long value %X>", *((CK_ULONG *) *ckpObjectPtr));
1001         return;
1002     }
1003 
1004     jBooleanClass = (*env)->FindClass(env, "java/lang/Boolean");
1005     if (jBooleanClass == NULL) { return; }
1006     if ((*env)->IsInstanceOf(env, jObject, jBooleanClass)) {
1007         *ckpObjectPtr = jBooleanObjectToCKBBoolPtr(env, jObject);
1008         *ckpLength = sizeof(CK_BBOOL);
1009         TRACE0(" <converted boolean value ");
1010         TRACE0((*((CK_BBOOL *) *ckpObjectPtr) == TRUE) ? "TRUE>" : "FALSE>");
1011         return;
1012     }
1013 
1014     jByteArrayClass = (*env)->FindClass(env, "[B");
1015     if (jByteArrayClass == NULL) { return; }
1016     if ((*env)->IsInstanceOf(env, jObject, jByteArrayClass)) {
1017         jByteArrayToCKByteArray(env, jObject, (CK_BYTE_PTR*)ckpObjectPtr, ckpLength);
1018         return;
1019     }
1020 
1021     jCharArrayClass = (*env)->FindClass(env, "[C");
1022     if (jCharArrayClass == NULL) { return; }
1023     if ((*env)->IsInstanceOf(env, jObject, jCharArrayClass)) {
1024         jCharArrayToCKUTF8CharArray(env, jObject, (CK_UTF8CHAR_PTR*)ckpObjectPtr, ckpLength);
1025         return;
1026     }
1027 
1028     jByteClass = (*env)->FindClass(env, "java/lang/Byte");
1029     if (jByteClass == NULL) { return; }
1030     if ((*env)->IsInstanceOf(env, jObject, jByteClass)) {
1031         *ckpObjectPtr = jByteObjectToCKBytePtr(env, jObject);
1032         *ckpLength = sizeof(CK_BYTE);
1033         TRACE1("<converted byte value %X>", *((CK_BYTE *) *ckpObjectPtr));
1034         return;
1035     }
1036 
1037     jDateClass = (*env)->FindClass(env, CLASS_DATE);
1038     if (jDateClass == NULL) { return; }
1039     if ((*env)->IsInstanceOf(env, jObject, jDateClass)) {
1040         *ckpObjectPtr = jDateObjectPtrToCKDatePtr(env, jObject);
1041         *ckpLength = sizeof(CK_DATE);
1042         TRACE3("<converted date value %.4s-%.2s-%.2s>", (*((CK_DATE *) *ckpObjectPtr)).year, (*((CK_DATE *) *ckpObjectPtr)).month, (*((CK_DATE *) *ckpObjectPtr)).day);
1043         return;
1044     }
1045 
1046     jCharacterClass = (*env)->FindClass(env, "java/lang/Character");
1047     if (jCharacterClass == NULL) { return; }
1048     if ((*env)->IsInstanceOf(env, jObject, jCharacterClass)) {
1049         *ckpObjectPtr = jCharObjectToCKCharPtr(env, jObject);
1050         *ckpLength = sizeof(CK_UTF8CHAR);
1051         TRACE1("<converted char value %c>", *((CK_CHAR *) *ckpObjectPtr));
1052         return;
1053     }
1054 
1055     jIntegerClass = (*env)->FindClass(env, "java/lang/Integer");
1056     if (jIntegerClass == NULL) { return; }
1057     if ((*env)->IsInstanceOf(env, jObject, jIntegerClass)) {
1058         *ckpObjectPtr = jIntegerObjectToCKULongPtr(env, jObject);
1059         *ckpLength = sizeof(CK_ULONG);
1060         TRACE1("<converted integer value %X>", *((CK_ULONG *) *ckpObjectPtr));
1061         return;
1062     }
1063 
1064     jBooleanArrayClass = (*env)->FindClass(env, "[Z");
1065     if (jBooleanArrayClass == NULL) { return; }
1066     if ((*env)->IsInstanceOf(env, jObject, jBooleanArrayClass)) {
1067         jBooleanArrayToCKBBoolArray(env, jObject, (CK_BBOOL**)ckpObjectPtr, ckpLength);
1068         return;
1069     }
1070 
1071     jIntArrayClass = (*env)->FindClass(env, "[I");
1072     if (jIntArrayClass == NULL) { return; }
1073     if ((*env)->IsInstanceOf(env, jObject, jIntArrayClass)) {
1074         jLongArrayToCKULongArray(env, jObject, (CK_ULONG_PTR*)ckpObjectPtr, ckpLength);
1075         return;
1076     }
1077 
1078     jLongArrayClass = (*env)->FindClass(env, "[J");
1079     if (jLongArrayClass == NULL) { return; }
1080     if ((*env)->IsInstanceOf(env, jObject, jLongArrayClass)) {
1081         jLongArrayToCKULongArray(env, jObject, (CK_ULONG_PTR*)ckpObjectPtr, ckpLength);
1082         return;
1083     }
1084 
1085     jStringClass = (*env)->FindClass(env, "java/lang/String");
1086     if (jStringClass == NULL) { return; }
1087     if ((*env)->IsInstanceOf(env, jObject, jStringClass)) {
1088         jStringToCKUTF8CharArray(env, jObject, (CK_UTF8CHAR_PTR*)ckpObjectPtr, ckpLength);
1089         return;
1090     }
1091 
1092     /* type of jObject unknown, throw PKCS11RuntimeException */
1093     jObjectClass = (*env)->FindClass(env, "java/lang/Object");
1094     if (jObjectClass == NULL) { return; }
1095     jMethod = (*env)->GetMethodID(env, jObjectClass, "getClass", "()Ljava/lang/Class;");
1096     if (jMethod == NULL) { return; }
1097     jClassObject = (*env)->CallObjectMethod(env, jObject, jMethod);
1098     assert(jClassObject != 0);
1099     jClassClass = (*env)->FindClass(env, "java/lang/Class");
1100     if (jClassClass == NULL) { return; }
1101     jMethod = (*env)->GetMethodID(env, jClassClass, "getName", "()Ljava/lang/String;");
1102     if (jMethod == NULL) { return; }
1103     jClassNameString = (jstring)
1104         (*env)->CallObjectMethod(env, jClassObject, jMethod);
1105     assert(jClassNameString != 0);
1106     classNameString = (char*)
1107         (*env)->GetStringUTFChars(env, jClassNameString, NULL);
1108     if (classNameString == NULL) { return; }
1109     exceptionMsgPrefix = "Java object of this class cannot be converted to native PKCS#11 type: ";
1110     exceptionMsg = (char *)
1111         malloc((strlen(exceptionMsgPrefix) + strlen(classNameString) + 1));
1112     if (exceptionMsg == NULL) {
1113         (*env)->ReleaseStringUTFChars(env, jClassNameString, classNameString);
1114         throwOutOfMemoryError(env, 0);
1115         return;
1116     }
1117     strcpy(exceptionMsg, exceptionMsgPrefix);
1118     strcat(exceptionMsg, classNameString);
1119     (*env)->ReleaseStringUTFChars(env, jClassNameString, classNameString);
1120     throwPKCS11RuntimeException(env, exceptionMsg);
1121     free(exceptionMsg);
1122     *ckpObjectPtr = NULL;
1123     *ckpLength = 0;
1124 
1125     TRACE0("FINISHED\n");
1126 }
1127 
1128 #ifdef P11_MEMORYDEBUG
1129 
1130 #undef malloc
1131 #undef free
1132 
1133 void *p11malloc(size_t c, char *file, int line) {
1134     void *p = malloc(c);
1135     printf("malloc\t%08x\t%d\t%s:%d\n", p, c, file, line); fflush(stdout);
1136     return p;
1137 }
1138 
1139 void p11free(void *p, char *file, int line) {
1140     printf("free\t%08x\t\t%s:%d\n", p, file, line); fflush(stdout);
1141     free(p);
1142 }
1143 
1144 #endif
1145 
1146 // prints a message to stdout if debug output is enabled
1147 void printDebug(const char *format, ...) {
1148     if (debug == JNI_TRUE) {
1149         va_list args;
1150         fprintf(stdout, "sunpkcs11: ");
1151         va_start(args, format);
1152         vfprintf(stdout, format, args);
1153         va_end(args);
1154         fflush(stdout);
1155     }
1156 }
1157