1 /*
2 * Copyright (c) 2003, 2019, 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 */
createLockObject(JNIEnv * env)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 */
destroyLockObject(JNIEnv * env,jobject jLockObject)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 */
putModuleEntry(JNIEnv * env,jobject pkcs11Implementation,ModuleData * moduleData)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 */
getModuleEntry(JNIEnv * env,jobject pkcs11Implementation)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
getFunctionList(JNIEnv * env,jobject pkcs11Implementation)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 */
isModulePresent(JNIEnv * env,jobject pkcs11Implementation)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 */
removeModuleEntry(JNIEnv * env,jobject pkcs11Implementation)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 */
removeAllModuleEntries(JNIEnv * env)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 */
ckAssertReturnValueOK(JNIEnv * env,CK_RV returnValue)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 */
throwByName(JNIEnv * env,const char * name,const char * msg)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 */
throwOutOfMemoryError(JNIEnv * env,const char * msg)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 */
throwNullPointerException(JNIEnv * env,const char * msg)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 */
throwIOException(JNIEnv * env,const char * msg)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 */
throwPKCS11RuntimeException(JNIEnv * env,const char * message)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 */
throwDisconnectedRuntimeException(JNIEnv * env)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 */
freeCKAttributeArray(CK_ATTRIBUTE_PTR attrPtr,int len)280 void freeCKAttributeArray(CK_ATTRIBUTE_PTR attrPtr, int len) {
281 if (attrPtr != NULL) {
282 int i;
283 for (i=0; i<len; i++) {
284 if (attrPtr[i].pValue != NULL_PTR) {
285 free(attrPtr[i].pValue);
286 }
287 }
288 free(attrPtr);
289 }
290 }
291
292 /* This function frees the specified CK_MECHANISM_PTR pointer and its
293 * pParameter including mechanism-specific memory allocations.
294 *
295 * @param mechPtr pointer to the to-be-freed CK_MECHANISM structure.
296 */
freeCKMechanismPtr(CK_MECHANISM_PTR mechPtr)297 void freeCKMechanismPtr(CK_MECHANISM_PTR mechPtr) {
298 void *tmp;
299 CK_SSL3_MASTER_KEY_DERIVE_PARAMS *sslMkdTmp;
300 CK_SSL3_KEY_MAT_PARAMS* sslKmTmp;
301 CK_TLS12_MASTER_KEY_DERIVE_PARAMS *tlsMkdTmp;
302 CK_TLS12_KEY_MAT_PARAMS* tlsKmTmp;
303
304 if (mechPtr != NULL) {
305 TRACE2("DEBUG freeCKMechanismPtr: free pMech %p (mech 0x%lX)\n",
306 mechPtr, mechPtr->mechanism);
307 if (mechPtr->pParameter != NULL) {
308 tmp = mechPtr->pParameter;
309 switch (mechPtr->mechanism) {
310 case CKM_AES_GCM:
311 if (mechPtr->ulParameterLen == sizeof(CK_GCM_PARAMS_NO_IVBITS)) {
312 TRACE0("[ GCM_PARAMS w/o ulIvBits ]\n");
313 free(((CK_GCM_PARAMS_NO_IVBITS*)tmp)->pIv);
314 free(((CK_GCM_PARAMS_NO_IVBITS*)tmp)->pAAD);
315 } else if (mechPtr->ulParameterLen == sizeof(CK_GCM_PARAMS)) {
316 TRACE0("[ GCM_PARAMS ]\n");
317 free(((CK_GCM_PARAMS*)tmp)->pIv);
318 free(((CK_GCM_PARAMS*)tmp)->pAAD);
319 }
320 break;
321 case CKM_AES_CCM:
322 TRACE0("[ CK_CCM_PARAMS ]\n");
323 free(((CK_CCM_PARAMS*)tmp)->pNonce);
324 free(((CK_CCM_PARAMS*)tmp)->pAAD);
325 break;
326 case CKM_TLS_PRF:
327 case CKM_NSS_TLS_PRF_GENERAL:
328 TRACE0("[ CK_TLS_PRF_PARAMS ]\n");
329 free(((CK_TLS_PRF_PARAMS*)tmp)->pSeed);
330 free(((CK_TLS_PRF_PARAMS*)tmp)->pLabel);
331 free(((CK_TLS_PRF_PARAMS*)tmp)->pulOutputLen);
332 free(((CK_TLS_PRF_PARAMS*)tmp)->pOutput);
333 break;
334 case CKM_SSL3_MASTER_KEY_DERIVE:
335 case CKM_TLS_MASTER_KEY_DERIVE:
336 case CKM_SSL3_MASTER_KEY_DERIVE_DH:
337 case CKM_TLS_MASTER_KEY_DERIVE_DH:
338 sslMkdTmp = tmp;
339 TRACE0("[ CK_SSL3_MASTER_KEY_DERIVE_PARAMS ]\n");
340 free(sslMkdTmp->RandomInfo.pClientRandom);
341 free(sslMkdTmp->RandomInfo.pServerRandom);
342 free(sslMkdTmp->pVersion);
343 break;
344 case CKM_SSL3_KEY_AND_MAC_DERIVE:
345 case CKM_TLS_KEY_AND_MAC_DERIVE:
346 sslKmTmp = tmp;
347 TRACE0("[ CK_SSL3_KEY_MAT_PARAMS ]\n");
348 free(sslKmTmp->RandomInfo.pClientRandom);
349 free(sslKmTmp->RandomInfo.pServerRandom);
350 if (sslKmTmp->pReturnedKeyMaterial != NULL) {
351 free(sslKmTmp->pReturnedKeyMaterial->pIVClient);
352 free(sslKmTmp->pReturnedKeyMaterial->pIVServer);
353 free(sslKmTmp->pReturnedKeyMaterial);
354 }
355 break;
356 case CKM_TLS12_MASTER_KEY_DERIVE:
357 case CKM_TLS12_MASTER_KEY_DERIVE_DH:
358 tlsMkdTmp = tmp;
359 TRACE0("[ CK_TLS12_MASTER_KEY_DERIVE_PARAMS ]\n");
360 free(tlsMkdTmp->RandomInfo.pClientRandom);
361 free(tlsMkdTmp->RandomInfo.pServerRandom);
362 free(tlsMkdTmp->pVersion);
363 break;
364 case CKM_TLS12_KEY_AND_MAC_DERIVE:
365 tlsKmTmp = tmp;
366 TRACE0("[ CK_TLS12_KEY_MAT_PARAMS ]\n");
367 free(tlsKmTmp->RandomInfo.pClientRandom);
368 free(tlsKmTmp->RandomInfo.pServerRandom);
369 if (tlsKmTmp->pReturnedKeyMaterial != NULL) {
370 free(tlsKmTmp->pReturnedKeyMaterial->pIVClient);
371 free(tlsKmTmp->pReturnedKeyMaterial->pIVServer);
372 free(tlsKmTmp->pReturnedKeyMaterial);
373 }
374 break;
375 case CKM_ECDH1_DERIVE:
376 case CKM_ECDH1_COFACTOR_DERIVE:
377 TRACE0("[ CK_ECDH1_DERIVE_PARAMS ]\n");
378 free(((CK_ECDH1_DERIVE_PARAMS *)tmp)->pSharedData);
379 free(((CK_ECDH1_DERIVE_PARAMS *)tmp)->pPublicData);
380 break;
381 case CKM_TLS_MAC:
382 case CKM_AES_CTR:
383 case CKM_RSA_PKCS_PSS:
384 case CKM_CAMELLIA_CTR:
385 // params do not contain pointers
386 break;
387 default:
388 // currently unsupported mechs by SunPKCS11 provider
389 // CKM_RSA_PKCS_OAEP, CKM_ECMQV_DERIVE,
390 // CKM_X9_42_*, CKM_KEA_DERIVE, CKM_RC2_*, CKM_RC5_*,
391 // CKM_SKIPJACK_*, CKM_KEY_WRAP_SET_OAEP, CKM_PKCS5_PBKD2,
392 // PBE mechs, WTLS mechs, CMS mechs,
393 // CKM_EXTRACT_KEY_FROM_KEY, CKM_OTP, CKM_KIP,
394 // CKM_DSA_PARAMETER_GEN?, CKM_GOSTR3410_*
395 // CK_any_CBC_ENCRYPT_DATA?
396 TRACE0("ERROR: UNSUPPORTED CK_MECHANISM\n");
397 break;
398 }
399 TRACE1("\t=> freed param %p\n", tmp);
400 free(tmp);
401 } else {
402 TRACE0("\t=> param NULL\n");
403 }
404 free(mechPtr);
405 TRACE0("FINISHED\n");
406 }
407 }
408
409 /* This function replaces the CK_GCM_PARAMS_NO_IVBITS structure associated
410 * with the specified CK_MECHANISM structure with CK_GCM_PARAMS
411 * structure.
412 *
413 * @param mechPtr pointer to the CK_MECHANISM structure containing
414 * the to-be-converted CK_GCM_PARAMS_NO_IVBITS structure.
415 * @return pointer to the CK_MECHANISM structure containing the
416 * converted CK_GCM_PARAMS structure or NULL if no conversion took place.
417 */
updateGCMParams(JNIEnv * env,CK_MECHANISM_PTR mechPtr)418 CK_MECHANISM_PTR updateGCMParams(JNIEnv *env, CK_MECHANISM_PTR mechPtr) {
419 CK_GCM_PARAMS* pGcmParams2 = NULL;
420 CK_GCM_PARAMS_NO_IVBITS* pParams = NULL;
421 if ((mechPtr->mechanism == CKM_AES_GCM) &&
422 (mechPtr->pParameter != NULL_PTR) &&
423 (mechPtr->ulParameterLen == sizeof(CK_GCM_PARAMS_NO_IVBITS))) {
424 pGcmParams2 = calloc(1, sizeof(CK_GCM_PARAMS));
425 if (pGcmParams2 == NULL) {
426 throwOutOfMemoryError(env, 0);
427 return NULL;
428 }
429 pParams = (CK_GCM_PARAMS_NO_IVBITS*) mechPtr->pParameter;
430 pGcmParams2->pIv = pParams->pIv;
431 pGcmParams2->ulIvLen = pParams->ulIvLen;
432 pGcmParams2->ulIvBits = (pGcmParams2->ulIvLen << 3);
433 pGcmParams2->pAAD = pParams->pAAD;
434 pGcmParams2->ulAADLen = pParams->ulAADLen;
435 pGcmParams2->ulTagBits = pParams->ulTagBits;
436 TRACE1("DEBUG updateGCMParams: pMech %p\n", mechPtr);
437 TRACE2("\t=> GCM param w/o ulIvBits %p => GCM param %p\n", pParams,
438 pGcmParams2);
439 free(pParams);
440 mechPtr->pParameter = pGcmParams2;
441 mechPtr->ulParameterLen = sizeof(CK_GCM_PARAMS);
442 return mechPtr;
443 } else {
444 TRACE0("DEBUG updateGCMParams: no conversion done\n");
445 }
446 return NULL;
447 }
448
449 /*
450 * the following functions convert Java arrays to PKCS#11 array pointers and
451 * their array length and vice versa
452 *
453 * void j<Type>ArrayToCK<Type>Array(JNIEnv *env,
454 * const j<Type>Array jArray,
455 * CK_<Type>_PTR *ckpArray,
456 * CK_ULONG_PTR ckLength);
457 *
458 * j<Type>Array ck<Type>ArrayToJ<Type>Array(JNIEnv *env,
459 * const CK_<Type>_PTR ckpArray,
460 * CK_ULONG ckLength);
461 *
462 * PKCS#11 arrays consist always of a pointer to the beginning of the array and
463 * the array length whereas Java arrays carry their array length.
464 *
465 * The Functions to convert a Java array to a PKCS#11 array are void functions.
466 * Their arguments are the Java array object to convert, the reference to the
467 * array pointer, where the new PKCS#11 array should be stored and the reference
468 * to the array length where the PKCS#11 array length should be stored. These two
469 * references must not be NULL_PTR.
470 *
471 * The functions first obtain the array length of the Java array and then allocate
472 * the memory for the PKCS#11 array and set the array length. Then each element
473 * gets converted depending on their type. After use the allocated memory of the
474 * PKCS#11 array has to be explicitly freed.
475 *
476 * The Functions to convert a PKCS#11 array to a Java array get the PKCS#11 array
477 * pointer and the array length and they return the new Java array object. The
478 * Java array does not need to get freed after use.
479 */
480
481 /*
482 * converts a jbooleanArray to a CK_BBOOL array. The allocated memory has to be freed after use!
483 *
484 * @param env - used to call JNI funktions to get the array informtaion
485 * @param jArray - the Java array to convert
486 * @param ckpArray - the reference, where the pointer to the new CK_BBOOL array will be stored
487 * @param ckpLength - the reference, where the array length will be stored
488 */
jBooleanArrayToCKBBoolArray(JNIEnv * env,const jbooleanArray jArray,CK_BBOOL ** ckpArray,CK_ULONG_PTR ckpLength)489 void jBooleanArrayToCKBBoolArray(JNIEnv *env, const jbooleanArray jArray, CK_BBOOL **ckpArray, CK_ULONG_PTR ckpLength)
490 {
491 jboolean* jpTemp;
492 CK_ULONG i;
493
494 if(jArray == NULL) {
495 *ckpArray = NULL_PTR;
496 *ckpLength = 0L;
497 return;
498 }
499 *ckpLength = (*env)->GetArrayLength(env, jArray);
500 jpTemp = (jboolean*) calloc(*ckpLength, sizeof(jboolean));
501 if (jpTemp == NULL) {
502 throwOutOfMemoryError(env, 0);
503 return;
504 }
505 (*env)->GetBooleanArrayRegion(env, jArray, 0, *ckpLength, jpTemp);
506 if ((*env)->ExceptionCheck(env)) {
507 free(jpTemp);
508 return;
509 }
510
511 *ckpArray = (CK_BBOOL*) calloc (*ckpLength, sizeof(CK_BBOOL));
512 if (*ckpArray == NULL) {
513 free(jpTemp);
514 throwOutOfMemoryError(env, 0);
515 return;
516 }
517 for (i=0; i<(*ckpLength); i++) {
518 (*ckpArray)[i] = jBooleanToCKBBool(jpTemp[i]);
519 }
520 free(jpTemp);
521 }
522
523 /*
524 * converts a jbyteArray to a CK_BYTE array. The allocated memory has to be freed after use!
525 *
526 * @param env - used to call JNI funktions to get the array informtaion
527 * @param jArray - the Java array to convert
528 * @param ckpArray - the reference, where the pointer to the new CK_BYTE array will be stored
529 * @param ckpLength - the reference, where the array length will be stored
530 */
jByteArrayToCKByteArray(JNIEnv * env,const jbyteArray jArray,CK_BYTE_PTR * ckpArray,CK_ULONG_PTR ckpLength)531 void jByteArrayToCKByteArray(JNIEnv *env, const jbyteArray jArray, CK_BYTE_PTR *ckpArray, CK_ULONG_PTR ckpLength)
532 {
533 jbyte* jpTemp;
534 CK_ULONG i;
535
536 if(jArray == NULL) {
537 *ckpArray = NULL_PTR;
538 *ckpLength = 0L;
539 return;
540 }
541 *ckpLength = (*env)->GetArrayLength(env, jArray);
542 jpTemp = (jbyte*) calloc(*ckpLength, sizeof(jbyte));
543 if (jpTemp == NULL) {
544 throwOutOfMemoryError(env, 0);
545 return;
546 }
547 (*env)->GetByteArrayRegion(env, jArray, 0, *ckpLength, jpTemp);
548 if ((*env)->ExceptionCheck(env)) {
549 free(jpTemp);
550 return;
551 }
552
553 /* if CK_BYTE is the same size as jbyte, we save an additional copy */
554 if (sizeof(CK_BYTE) == sizeof(jbyte)) {
555 *ckpArray = (CK_BYTE_PTR) jpTemp;
556 } else {
557 *ckpArray = (CK_BYTE_PTR) calloc (*ckpLength, sizeof(CK_BYTE));
558 if (*ckpArray == NULL) {
559 free(jpTemp);
560 throwOutOfMemoryError(env, 0);
561 return;
562 }
563 for (i=0; i<(*ckpLength); i++) {
564 (*ckpArray)[i] = jByteToCKByte(jpTemp[i]);
565 }
566 free(jpTemp);
567 }
568 }
569
570 /*
571 * converts a jlongArray to a CK_ULONG array. The allocated memory has to be freed after use!
572 *
573 * @param env - used to call JNI funktions to get the array informtaion
574 * @param jArray - the Java array to convert
575 * @param ckpArray - the reference, where the pointer to the new CK_ULONG array will be stored
576 * @param ckpLength - the reference, where the array length will be stored
577 */
jLongArrayToCKULongArray(JNIEnv * env,const jlongArray jArray,CK_ULONG_PTR * ckpArray,CK_ULONG_PTR ckpLength)578 void jLongArrayToCKULongArray(JNIEnv *env, const jlongArray jArray, CK_ULONG_PTR *ckpArray, CK_ULONG_PTR ckpLength)
579 {
580 jlong* jTemp;
581 CK_ULONG i;
582
583 if(jArray == NULL) {
584 *ckpArray = NULL_PTR;
585 *ckpLength = 0L;
586 return;
587 }
588 *ckpLength = (*env)->GetArrayLength(env, jArray);
589 jTemp = (jlong*) calloc(*ckpLength, sizeof(jlong));
590 if (jTemp == NULL) {
591 throwOutOfMemoryError(env, 0);
592 return;
593 }
594 (*env)->GetLongArrayRegion(env, jArray, 0, *ckpLength, jTemp);
595 if ((*env)->ExceptionCheck(env)) {
596 free(jTemp);
597 return;
598 }
599
600 *ckpArray = (CK_ULONG_PTR) calloc(*ckpLength, sizeof(CK_ULONG));
601 if (*ckpArray == NULL) {
602 free(jTemp);
603 throwOutOfMemoryError(env, 0);
604 return;
605 }
606 for (i=0; i<(*ckpLength); i++) {
607 (*ckpArray)[i] = jLongToCKULong(jTemp[i]);
608 }
609 free(jTemp);
610 }
611
612 /*
613 * converts a jcharArray to a CK_CHAR array. The allocated memory has to be freed after use!
614 *
615 * @param env - used to call JNI funktions to get the array informtaion
616 * @param jArray - the Java array to convert
617 * @param ckpArray - the reference, where the pointer to the new CK_CHAR array will be stored
618 * @param ckpLength - the reference, where the array length will be stored
619 */
jCharArrayToCKCharArray(JNIEnv * env,const jcharArray jArray,CK_CHAR_PTR * ckpArray,CK_ULONG_PTR ckpLength)620 void jCharArrayToCKCharArray(JNIEnv *env, const jcharArray jArray, CK_CHAR_PTR *ckpArray, CK_ULONG_PTR ckpLength)
621 {
622 jchar* jpTemp;
623 CK_ULONG i;
624
625 if(jArray == NULL) {
626 *ckpArray = NULL_PTR;
627 *ckpLength = 0L;
628 return;
629 }
630 *ckpLength = (*env)->GetArrayLength(env, jArray);
631 jpTemp = (jchar*) calloc(*ckpLength, sizeof(jchar));
632 if (jpTemp == NULL) {
633 throwOutOfMemoryError(env, 0);
634 return;
635 }
636 (*env)->GetCharArrayRegion(env, jArray, 0, *ckpLength, jpTemp);
637 if ((*env)->ExceptionCheck(env)) {
638 free(jpTemp);
639 return;
640 }
641
642 *ckpArray = (CK_CHAR_PTR) calloc (*ckpLength, sizeof(CK_CHAR));
643 if (*ckpArray == NULL) {
644 free(jpTemp);
645 throwOutOfMemoryError(env, 0);
646 return;
647 }
648 for (i=0; i<(*ckpLength); i++) {
649 (*ckpArray)[i] = jCharToCKChar(jpTemp[i]);
650 }
651 free(jpTemp);
652 }
653
654 /*
655 * converts a jcharArray to a CK_UTF8CHAR array. The allocated memory has to be freed after use!
656 *
657 * @param env - used to call JNI funktions to get the array informtaion
658 * @param jArray - the Java array to convert
659 * @param ckpArray - the reference, where the pointer to the new CK_UTF8CHAR array will be stored
660 * @param ckpLength - the reference, where the array length will be stored
661 */
jCharArrayToCKUTF8CharArray(JNIEnv * env,const jcharArray jArray,CK_UTF8CHAR_PTR * ckpArray,CK_ULONG_PTR ckpLength)662 void jCharArrayToCKUTF8CharArray(JNIEnv *env, const jcharArray jArray, CK_UTF8CHAR_PTR *ckpArray, CK_ULONG_PTR ckpLength)
663 {
664 jchar* jTemp;
665 CK_ULONG i;
666
667 if(jArray == NULL) {
668 *ckpArray = NULL_PTR;
669 *ckpLength = 0L;
670 return;
671 }
672 *ckpLength = (*env)->GetArrayLength(env, jArray);
673 jTemp = (jchar*) calloc(*ckpLength, sizeof(jchar));
674 if (jTemp == NULL) {
675 throwOutOfMemoryError(env, 0);
676 return;
677 }
678 (*env)->GetCharArrayRegion(env, jArray, 0, *ckpLength, jTemp);
679 if ((*env)->ExceptionCheck(env)) {
680 free(jTemp);
681 return;
682 }
683
684 *ckpArray = (CK_UTF8CHAR_PTR) calloc(*ckpLength, sizeof(CK_UTF8CHAR));
685 if (*ckpArray == NULL) {
686 free(jTemp);
687 throwOutOfMemoryError(env, 0);
688 return;
689 }
690 for (i=0; i<(*ckpLength); i++) {
691 (*ckpArray)[i] = jCharToCKUTF8Char(jTemp[i]);
692 }
693 free(jTemp);
694 }
695
696 /*
697 * converts a jstring to a CK_CHAR array. The allocated memory has to be freed after use!
698 *
699 * @param env - used to call JNI funktions to get the array informtaion
700 * @param jArray - the Java array to convert
701 * @param ckpArray - the reference, where the pointer to the new CK_CHAR array will be stored
702 * @param ckpLength - the reference, where the array length will be stored
703 */
jStringToCKUTF8CharArray(JNIEnv * env,const jstring jArray,CK_UTF8CHAR_PTR * ckpArray,CK_ULONG_PTR ckpLength)704 void jStringToCKUTF8CharArray(JNIEnv *env, const jstring jArray, CK_UTF8CHAR_PTR *ckpArray, CK_ULONG_PTR ckpLength)
705 {
706 const char* pCharArray;
707 jboolean isCopy;
708
709 if(jArray == NULL) {
710 *ckpArray = NULL_PTR;
711 *ckpLength = 0L;
712 return;
713 }
714
715 pCharArray = (*env)->GetStringUTFChars(env, jArray, &isCopy);
716 if (pCharArray == NULL) { return; }
717
718 *ckpLength = (CK_ULONG) strlen(pCharArray);
719 *ckpArray = (CK_UTF8CHAR_PTR) calloc(*ckpLength + 1, sizeof(CK_UTF8CHAR));
720 if (*ckpArray == NULL) {
721 (*env)->ReleaseStringUTFChars(env, (jstring) jArray, pCharArray);
722 throwOutOfMemoryError(env, 0);
723 return;
724 }
725 strcpy((char*)*ckpArray, pCharArray);
726 (*env)->ReleaseStringUTFChars(env, (jstring) jArray, pCharArray);
727 }
728
729 /*
730 * converts a jobjectArray with Java Attributes to a CK_ATTRIBUTE array. The allocated memory
731 * has to be freed after use!
732 *
733 * @param env - used to call JNI funktions to get the array informtaion
734 * @param jArray - the Java Attribute array (template) to convert
735 * @param ckpArray - the reference, where the pointer to the new CK_ATTRIBUTE array will be
736 * stored
737 * @param ckpLength - the reference, where the array length will be stored
738 */
jAttributeArrayToCKAttributeArray(JNIEnv * env,jobjectArray jArray,CK_ATTRIBUTE_PTR * ckpArray,CK_ULONG_PTR ckpLength)739 void jAttributeArrayToCKAttributeArray(JNIEnv *env, jobjectArray jArray, CK_ATTRIBUTE_PTR *ckpArray, CK_ULONG_PTR ckpLength)
740 {
741 CK_ULONG i;
742 jlong jLength;
743 jobject jAttribute;
744
745 TRACE0("\nDEBUG: jAttributeArrayToCKAttributeArray");
746 if (jArray == NULL) {
747 *ckpArray = NULL_PTR;
748 *ckpLength = 0L;
749 return;
750 }
751 jLength = (*env)->GetArrayLength(env, jArray);
752 *ckpLength = jLongToCKULong(jLength);
753 *ckpArray = (CK_ATTRIBUTE_PTR) calloc(*ckpLength, sizeof(CK_ATTRIBUTE));
754 if (*ckpArray == NULL) {
755 throwOutOfMemoryError(env, 0);
756 return;
757 }
758 TRACE1(", converting %lld attributes", (long long int) jLength);
759 for (i=0; i<(*ckpLength); i++) {
760 TRACE1(", getting %lu. attribute", i);
761 jAttribute = (*env)->GetObjectArrayElement(env, jArray, i);
762 if ((*env)->ExceptionCheck(env)) {
763 freeCKAttributeArray(*ckpArray, i);
764 return;
765 }
766 TRACE1(", jAttribute , converting %lu. attribute", i);
767 (*ckpArray)[i] = jAttributeToCKAttribute(env, jAttribute);
768 if ((*env)->ExceptionCheck(env)) {
769 freeCKAttributeArray(*ckpArray, i);
770 return;
771 }
772 }
773 TRACE0("FINISHED\n");
774 }
775
776 /*
777 * converts a CK_BYTE array and its length to a jbyteArray.
778 *
779 * @param env - used to call JNI funktions to create the new Java array
780 * @param ckpArray - the pointer to the CK_BYTE array to convert
781 * @param ckpLength - the length of the array to convert
782 * @return - the new Java byte array or NULL if error occurred
783 */
ckByteArrayToJByteArray(JNIEnv * env,const CK_BYTE_PTR ckpArray,CK_ULONG ckLength)784 jbyteArray ckByteArrayToJByteArray(JNIEnv *env, const CK_BYTE_PTR ckpArray, CK_ULONG ckLength)
785 {
786 CK_ULONG i;
787 jbyte* jpTemp;
788 jbyteArray jArray;
789
790 /* if CK_BYTE is the same size as jbyte, we save an additional copy */
791 if (sizeof(CK_BYTE) == sizeof(jbyte)) {
792 jpTemp = (jbyte*) ckpArray;
793 } else {
794 jpTemp = (jbyte*) calloc(ckLength, sizeof(jbyte));
795 if (jpTemp == NULL) {
796 throwOutOfMemoryError(env, 0);
797 return NULL;
798 }
799 for (i=0; i<ckLength; i++) {
800 jpTemp[i] = ckByteToJByte(ckpArray[i]);
801 }
802 }
803
804 jArray = (*env)->NewByteArray(env, ckULongToJSize(ckLength));
805 if (jArray != NULL) {
806 (*env)->SetByteArrayRegion(env, jArray, 0, ckULongToJSize(ckLength), jpTemp);
807 }
808
809 if (sizeof(CK_BYTE) != sizeof(jbyte)) { free(jpTemp); }
810
811 return jArray ;
812 }
813
814 /*
815 * converts a CK_ULONG array and its length to a jlongArray.
816 *
817 * @param env - used to call JNI funktions to create the new Java array
818 * @param ckpArray - the pointer to the CK_ULONG array to convert
819 * @param ckpLength - the length of the array to convert
820 * @return - the new Java long array
821 */
ckULongArrayToJLongArray(JNIEnv * env,const CK_ULONG_PTR ckpArray,CK_ULONG ckLength)822 jlongArray ckULongArrayToJLongArray(JNIEnv *env, const CK_ULONG_PTR ckpArray, CK_ULONG ckLength)
823 {
824 CK_ULONG i;
825 jlong* jpTemp;
826 jlongArray jArray;
827
828 jpTemp = (jlong*) calloc(ckLength, sizeof(jlong));
829 if (jpTemp == NULL) {
830 throwOutOfMemoryError(env, 0);
831 return NULL;
832 }
833 for (i=0; i<ckLength; i++) {
834 jpTemp[i] = ckLongToJLong(ckpArray[i]);
835 }
836 jArray = (*env)->NewLongArray(env, ckULongToJSize(ckLength));
837 if (jArray != NULL) {
838 (*env)->SetLongArrayRegion(env, jArray, 0, ckULongToJSize(ckLength), jpTemp);
839 }
840 free(jpTemp);
841
842 return jArray ;
843 }
844
845 /*
846 * converts a CK_CHAR array and its length to a jcharArray.
847 *
848 * @param env - used to call JNI funktions to create the new Java array
849 * @param ckpArray - the pointer to the CK_CHAR array to convert
850 * @param ckpLength - the length of the array to convert
851 * @return - the new Java char array
852 */
ckCharArrayToJCharArray(JNIEnv * env,const CK_CHAR_PTR ckpArray,CK_ULONG ckLength)853 jcharArray ckCharArrayToJCharArray(JNIEnv *env, const CK_CHAR_PTR ckpArray, CK_ULONG ckLength)
854 {
855 CK_ULONG i;
856 jchar* jpTemp;
857 jcharArray jArray;
858
859 jpTemp = (jchar*) calloc(ckLength, sizeof(jchar));
860 if (jpTemp == NULL) {
861 throwOutOfMemoryError(env, 0);
862 return NULL;
863 }
864 for (i=0; i<ckLength; i++) {
865 jpTemp[i] = ckCharToJChar(ckpArray[i]);
866 }
867 jArray = (*env)->NewCharArray(env, ckULongToJSize(ckLength));
868 if (jArray != NULL) {
869 (*env)->SetCharArrayRegion(env, jArray, 0, ckULongToJSize(ckLength), jpTemp);
870 }
871 free(jpTemp);
872
873 return jArray ;
874 }
875
876 /*
877 * converts a CK_UTF8CHAR array and its length to a jcharArray.
878 *
879 * @param env - used to call JNI funktions to create the new Java array
880 * @param ckpArray - the pointer to the CK_UTF8CHAR array to convert
881 * @param ckpLength - the length of the array to convert
882 * @return - the new Java char array
883 */
ckUTF8CharArrayToJCharArray(JNIEnv * env,const CK_UTF8CHAR_PTR ckpArray,CK_ULONG ckLength)884 jcharArray ckUTF8CharArrayToJCharArray(JNIEnv *env, const CK_UTF8CHAR_PTR ckpArray, CK_ULONG ckLength)
885 {
886 CK_ULONG i;
887 jchar* jpTemp;
888 jcharArray jArray;
889
890 jpTemp = (jchar*) calloc(ckLength, sizeof(jchar));
891 if (jpTemp == NULL) {
892 throwOutOfMemoryError(env, 0);
893 return NULL;
894 }
895 for (i=0; i<ckLength; i++) {
896 jpTemp[i] = ckUTF8CharToJChar(ckpArray[i]);
897 }
898 jArray = (*env)->NewCharArray(env, ckULongToJSize(ckLength));
899 if (jArray != NULL) {
900 (*env)->SetCharArrayRegion(env, jArray, 0, ckULongToJSize(ckLength), jpTemp);
901 }
902 free(jpTemp);
903
904 return jArray ;
905 }
906
907 /*
908 * the following functions convert Java objects to PKCS#11 pointers and the
909 * length in bytes and vice versa
910 *
911 * CK_<Type>_PTR j<Object>ToCK<Type>Ptr(JNIEnv *env, jobject jObject);
912 *
913 * jobject ck<Type>PtrToJ<Object>(JNIEnv *env, const CK_<Type>_PTR ckpValue);
914 *
915 * The functions that convert a Java object to a PKCS#11 pointer first allocate
916 * the memory for the PKCS#11 pointer. Then they set each element corresponding
917 * to the fields in the Java object to convert. After use the allocated memory of
918 * the PKCS#11 pointer has to be explicitly freed.
919 *
920 * The functions to convert a PKCS#11 pointer to a Java object create a new Java
921 * object first and than they set all fields in the object depending on the values
922 * of the type or structure where the PKCS#11 pointer points to.
923 */
924
925 /*
926 * converts a CK_BBOOL pointer to a Java boolean Object.
927 *
928 * @param env - used to call JNI funktions to create the new Java object
929 * @param ckpValue - the pointer to the CK_BBOOL value
930 * @return - the new Java boolean object with the boolean value
931 */
ckBBoolPtrToJBooleanObject(JNIEnv * env,const CK_BBOOL * ckpValue)932 jobject ckBBoolPtrToJBooleanObject(JNIEnv *env, const CK_BBOOL *ckpValue)
933 {
934 jclass jValueObjectClass;
935 jmethodID jConstructor;
936 jobject jValueObject;
937 jboolean jValue;
938
939 jValueObjectClass = (*env)->FindClass(env, "java/lang/Boolean");
940 if (jValueObjectClass == NULL) { return NULL; }
941 jConstructor = (*env)->GetMethodID(env, jValueObjectClass, "<init>", "(Z)V");
942 if (jConstructor == NULL) { return NULL; }
943 jValue = ckBBoolToJBoolean(*ckpValue);
944 jValueObject = (*env)->NewObject(env, jValueObjectClass, jConstructor, jValue);
945
946 return jValueObject ;
947 }
948
949 /*
950 * converts a CK_ULONG pointer to a Java long Object.
951 *
952 * @param env - used to call JNI funktions to create the new Java object
953 * @param ckpValue - the pointer to the CK_ULONG value
954 * @return - the new Java long object with the long value
955 */
ckULongPtrToJLongObject(JNIEnv * env,const CK_ULONG_PTR ckpValue)956 jobject ckULongPtrToJLongObject(JNIEnv *env, const CK_ULONG_PTR ckpValue)
957 {
958 jclass jValueObjectClass;
959 jmethodID jConstructor;
960 jobject jValueObject;
961 jlong jValue;
962
963 jValueObjectClass = (*env)->FindClass(env, "java/lang/Long");
964 if (jValueObjectClass == NULL) { return NULL; }
965 jConstructor = (*env)->GetMethodID(env, jValueObjectClass, "<init>", "(J)V");
966 if (jConstructor == NULL) { return NULL; }
967 jValue = ckULongToJLong(*ckpValue);
968 jValueObject = (*env)->NewObject(env, jValueObjectClass, jConstructor, jValue);
969
970 return jValueObject ;
971 }
972
973 /*
974 * converts a Java boolean object into a pointer to a CK_BBOOL value. The memory has to be
975 * freed after use!
976 *
977 * @param env - used to call JNI funktions to get the value out of the Java object
978 * @param jObject - the "java/lang/Boolean" object to convert
979 * @return - the pointer to the new CK_BBOOL value
980 */
jBooleanObjectToCKBBoolPtr(JNIEnv * env,jobject jObject)981 CK_BBOOL* jBooleanObjectToCKBBoolPtr(JNIEnv *env, jobject jObject)
982 {
983 jclass jObjectClass;
984 jmethodID jValueMethod;
985 jboolean jValue;
986 CK_BBOOL *ckpValue;
987
988 jObjectClass = (*env)->FindClass(env, "java/lang/Boolean");
989 if (jObjectClass == NULL) { return NULL; }
990 jValueMethod = (*env)->GetMethodID(env, jObjectClass, "booleanValue", "()Z");
991 if (jValueMethod == NULL) { return NULL; }
992 jValue = (*env)->CallBooleanMethod(env, jObject, jValueMethod);
993 ckpValue = (CK_BBOOL *) malloc(sizeof(CK_BBOOL));
994 if (ckpValue == NULL) {
995 throwOutOfMemoryError(env, 0);
996 return NULL;
997 }
998 *ckpValue = jBooleanToCKBBool(jValue);
999
1000 return ckpValue ;
1001 }
1002
1003 /*
1004 * converts a Java byte object into a pointer to a CK_BYTE value. The memory has to be
1005 * freed after use!
1006 *
1007 * @param env - used to call JNI funktions to get the value out of the Java object
1008 * @param jObject - the "java/lang/Byte" object to convert
1009 * @return - the pointer to the new CK_BYTE value
1010 */
jByteObjectToCKBytePtr(JNIEnv * env,jobject jObject)1011 CK_BYTE_PTR jByteObjectToCKBytePtr(JNIEnv *env, jobject jObject)
1012 {
1013 jclass jObjectClass;
1014 jmethodID jValueMethod;
1015 jbyte jValue;
1016 CK_BYTE_PTR ckpValue;
1017
1018 jObjectClass = (*env)->FindClass(env, "java/lang/Byte");
1019 if (jObjectClass == NULL) { return NULL; }
1020 jValueMethod = (*env)->GetMethodID(env, jObjectClass, "byteValue", "()B");
1021 if (jValueMethod == NULL) { return NULL; }
1022 jValue = (*env)->CallByteMethod(env, jObject, jValueMethod);
1023 ckpValue = (CK_BYTE_PTR) malloc(sizeof(CK_BYTE));
1024 if (ckpValue == NULL) {
1025 throwOutOfMemoryError(env, 0);
1026 return NULL;
1027 }
1028 *ckpValue = jByteToCKByte(jValue);
1029 return ckpValue ;
1030 }
1031
1032 /*
1033 * converts a Java integer object into a pointer to a CK_ULONG value. The memory has to be
1034 * freed after use!
1035 *
1036 * @param env - used to call JNI funktions to get the value out of the Java object
1037 * @param jObject - the "java/lang/Integer" object to convert
1038 * @return - the pointer to the new CK_ULONG value
1039 */
jIntegerObjectToCKULongPtr(JNIEnv * env,jobject jObject)1040 CK_ULONG* jIntegerObjectToCKULongPtr(JNIEnv *env, jobject jObject)
1041 {
1042 jclass jObjectClass;
1043 jmethodID jValueMethod;
1044 jint jValue;
1045 CK_ULONG *ckpValue;
1046
1047 jObjectClass = (*env)->FindClass(env, "java/lang/Integer");
1048 if (jObjectClass == NULL) { return NULL; }
1049 jValueMethod = (*env)->GetMethodID(env, jObjectClass, "intValue", "()I");
1050 if (jValueMethod == NULL) { return NULL; }
1051 jValue = (*env)->CallIntMethod(env, jObject, jValueMethod);
1052 ckpValue = (CK_ULONG *) malloc(sizeof(CK_ULONG));
1053 if (ckpValue == NULL) {
1054 throwOutOfMemoryError(env, 0);
1055 return NULL;
1056 }
1057 *ckpValue = jLongToCKLong(jValue);
1058 return ckpValue ;
1059 }
1060
1061 /*
1062 * converts a Java long object into a pointer to a CK_ULONG value. The memory has to be
1063 * freed after use!
1064 *
1065 * @param env - used to call JNI funktions to get the value out of the Java object
1066 * @param jObject - the "java/lang/Long" object to convert
1067 * @return - the pointer to the new CK_ULONG value
1068 */
jLongObjectToCKULongPtr(JNIEnv * env,jobject jObject)1069 CK_ULONG* jLongObjectToCKULongPtr(JNIEnv *env, jobject jObject)
1070 {
1071 jclass jObjectClass;
1072 jmethodID jValueMethod;
1073 jlong jValue;
1074 CK_ULONG *ckpValue;
1075
1076 jObjectClass = (*env)->FindClass(env, "java/lang/Long");
1077 if (jObjectClass == NULL) { return NULL; }
1078 jValueMethod = (*env)->GetMethodID(env, jObjectClass, "longValue", "()J");
1079 if (jValueMethod == NULL) { return NULL; }
1080 jValue = (*env)->CallLongMethod(env, jObject, jValueMethod);
1081 ckpValue = (CK_ULONG *) malloc(sizeof(CK_ULONG));
1082 if (ckpValue == NULL) {
1083 throwOutOfMemoryError(env, 0);
1084 return NULL;
1085 }
1086 *ckpValue = jLongToCKULong(jValue);
1087
1088 return ckpValue ;
1089 }
1090
1091 /*
1092 * converts a Java char object into a pointer to a CK_CHAR value. The memory has to be
1093 * freed after use!
1094 *
1095 * @param env - used to call JNI funktions to get the value out of the Java object
1096 * @param jObject - the "java/lang/Char" object to convert
1097 * @return - the pointer to the new CK_CHAR value
1098 */
jCharObjectToCKCharPtr(JNIEnv * env,jobject jObject)1099 CK_CHAR_PTR jCharObjectToCKCharPtr(JNIEnv *env, jobject jObject)
1100 {
1101 jclass jObjectClass;
1102 jmethodID jValueMethod;
1103 jchar jValue;
1104 CK_CHAR_PTR ckpValue;
1105
1106 jObjectClass = (*env)->FindClass(env, "java/lang/Char");
1107 if (jObjectClass == NULL) { return NULL; }
1108 jValueMethod = (*env)->GetMethodID(env, jObjectClass, "charValue", "()C");
1109 if (jValueMethod == NULL) { return NULL; }
1110 jValue = (*env)->CallCharMethod(env, jObject, jValueMethod);
1111 ckpValue = (CK_CHAR_PTR) malloc(sizeof(CK_CHAR));
1112 if (ckpValue == NULL) {
1113 throwOutOfMemoryError(env, 0);
1114 return NULL;
1115 }
1116 *ckpValue = jCharToCKChar(jValue);
1117
1118 return ckpValue ;
1119 }
1120
1121 /*
1122 * converts a Java object into a pointer to CK-type or a CK-structure with the length in Bytes.
1123 * The memory of the returned pointer MUST BE FREED BY CALLER!
1124 *
1125 * @param env - used to call JNI funktions to get the Java classes and objects
1126 * @param jObject - the Java object to convert
1127 * @param ckpLength - pointer to the length (bytes) of the newly-allocated CK-value or CK-structure
1128 * @return ckpObject - pointer to the newly-allocated CK-value or CK-structure
1129 */
jObjectToPrimitiveCKObjectPtr(JNIEnv * env,jobject jObject,CK_ULONG * ckpLength)1130 CK_VOID_PTR jObjectToPrimitiveCKObjectPtr(JNIEnv *env, jobject jObject, CK_ULONG *ckpLength)
1131 {
1132 jclass jLongClass, jBooleanClass, jByteArrayClass, jCharArrayClass;
1133 jclass jByteClass, jDateClass, jCharacterClass, jIntegerClass;
1134 jclass jBooleanArrayClass, jIntArrayClass, jLongArrayClass;
1135 jclass jStringClass;
1136 jclass jObjectClass, jClassClass;
1137 CK_VOID_PTR ckpObject;
1138 jmethodID jMethod;
1139 jobject jClassObject;
1140 jstring jClassNameString;
1141 char *classNameString, *exceptionMsgPrefix, *exceptionMsg;
1142
1143 TRACE0("\nDEBUG: jObjectToPrimitiveCKObjectPtr");
1144 if (jObject == NULL) {
1145 *ckpLength = 0;
1146 return NULL;
1147 }
1148
1149 jLongClass = (*env)->FindClass(env, "java/lang/Long");
1150 if (jLongClass == NULL) { return NULL; }
1151 if ((*env)->IsInstanceOf(env, jObject, jLongClass)) {
1152 ckpObject = jLongObjectToCKULongPtr(env, jObject);
1153 *ckpLength = sizeof(CK_ULONG);
1154 TRACE1("<converted long value %lu>", *((CK_ULONG *) ckpObject));
1155 return ckpObject;
1156 }
1157
1158 jBooleanClass = (*env)->FindClass(env, "java/lang/Boolean");
1159 if (jBooleanClass == NULL) { return NULL; }
1160 if ((*env)->IsInstanceOf(env, jObject, jBooleanClass)) {
1161 ckpObject = jBooleanObjectToCKBBoolPtr(env, jObject);
1162 *ckpLength = sizeof(CK_BBOOL);
1163 TRACE0(" <converted boolean value ");
1164 TRACE0((*((CK_BBOOL *) ckpObject) == TRUE) ? "TRUE>" : "FALSE>");
1165 return ckpObject;
1166 }
1167
1168 jByteArrayClass = (*env)->FindClass(env, "[B");
1169 if (jByteArrayClass == NULL) { return NULL; }
1170 if ((*env)->IsInstanceOf(env, jObject, jByteArrayClass)) {
1171 jByteArrayToCKByteArray(env, jObject, (CK_BYTE_PTR*) &ckpObject, ckpLength);
1172 return ckpObject;
1173 }
1174
1175 jCharArrayClass = (*env)->FindClass(env, "[C");
1176 if (jCharArrayClass == NULL) { return NULL; }
1177 if ((*env)->IsInstanceOf(env, jObject, jCharArrayClass)) {
1178 jCharArrayToCKUTF8CharArray(env, jObject, (CK_UTF8CHAR_PTR*) &ckpObject, ckpLength);
1179 return ckpObject;
1180 }
1181
1182 jByteClass = (*env)->FindClass(env, "java/lang/Byte");
1183 if (jByteClass == NULL) { return NULL; }
1184 if ((*env)->IsInstanceOf(env, jObject, jByteClass)) {
1185 ckpObject = jByteObjectToCKBytePtr(env, jObject);
1186 *ckpLength = sizeof(CK_BYTE);
1187 TRACE1("<converted byte value %X>", *((CK_BYTE *) ckpObject));
1188 return ckpObject;
1189 }
1190
1191 jDateClass = (*env)->FindClass(env, CLASS_DATE);
1192 if (jDateClass == NULL) { return NULL; }
1193 if ((*env)->IsInstanceOf(env, jObject, jDateClass)) {
1194 ckpObject = jDateObjectToCKDatePtr(env, jObject);
1195 *ckpLength = sizeof(CK_DATE);
1196 TRACE3("<converted date value %.4s-%.2s-%.2s>", ((CK_DATE *) ckpObject)->year,
1197 ((CK_DATE *) ckpObject)->month, ((CK_DATE *) ckpObject)->day);
1198 return ckpObject;
1199 }
1200
1201 jCharacterClass = (*env)->FindClass(env, "java/lang/Character");
1202 if (jCharacterClass == NULL) { return NULL; }
1203 if ((*env)->IsInstanceOf(env, jObject, jCharacterClass)) {
1204 ckpObject = jCharObjectToCKCharPtr(env, jObject);
1205 *ckpLength = sizeof(CK_UTF8CHAR);
1206 TRACE1("<converted char value %c>", *((CK_CHAR *) ckpObject));
1207 return ckpObject;
1208 }
1209
1210 jIntegerClass = (*env)->FindClass(env, "java/lang/Integer");
1211 if (jIntegerClass == NULL) { return NULL; }
1212 if ((*env)->IsInstanceOf(env, jObject, jIntegerClass)) {
1213 ckpObject = jIntegerObjectToCKULongPtr(env, jObject);
1214 *ckpLength = sizeof(CK_ULONG);
1215 TRACE1("<converted integer value %lu>", *((CK_ULONG *) ckpObject));
1216 return ckpObject;
1217 }
1218
1219 jBooleanArrayClass = (*env)->FindClass(env, "[Z");
1220 if (jBooleanArrayClass == NULL) { return NULL; }
1221 if ((*env)->IsInstanceOf(env, jObject, jBooleanArrayClass)) {
1222 jBooleanArrayToCKBBoolArray(env, jObject, (CK_BBOOL**) &ckpObject, ckpLength);
1223 return ckpObject;
1224 }
1225
1226 jIntArrayClass = (*env)->FindClass(env, "[I");
1227 if (jIntArrayClass == NULL) { return NULL; }
1228 if ((*env)->IsInstanceOf(env, jObject, jIntArrayClass)) {
1229 jLongArrayToCKULongArray(env, jObject, (CK_ULONG_PTR*) &ckpObject, ckpLength);
1230 return ckpObject;
1231 }
1232
1233 jLongArrayClass = (*env)->FindClass(env, "[J");
1234 if (jLongArrayClass == NULL) { return NULL; }
1235 if ((*env)->IsInstanceOf(env, jObject, jLongArrayClass)) {
1236 jLongArrayToCKULongArray(env, jObject, (CK_ULONG_PTR*) &ckpObject, ckpLength);
1237 return ckpObject;
1238 }
1239
1240 jStringClass = (*env)->FindClass(env, "java/lang/String");
1241 if (jStringClass == NULL) { return NULL; }
1242 if ((*env)->IsInstanceOf(env, jObject, jStringClass)) {
1243 jStringToCKUTF8CharArray(env, jObject, (CK_UTF8CHAR_PTR*) &ckpObject, ckpLength);
1244 return ckpObject;
1245 }
1246
1247 /* type of jObject unknown, throw PKCS11RuntimeException */
1248 jObjectClass = (*env)->FindClass(env, "java/lang/Object");
1249 if (jObjectClass == NULL) { return NULL; }
1250 jMethod = (*env)->GetMethodID(env, jObjectClass, "getClass", "()Ljava/lang/Class;");
1251 if (jMethod == NULL) { return NULL; }
1252 jClassObject = (*env)->CallObjectMethod(env, jObject, jMethod);
1253 assert(jClassObject != 0);
1254 jClassClass = (*env)->FindClass(env, "java/lang/Class");
1255 if (jClassClass == NULL) { return NULL; }
1256 jMethod = (*env)->GetMethodID(env, jClassClass, "getName", "()Ljava/lang/String;");
1257 if (jMethod == NULL) { return NULL; }
1258 jClassNameString = (jstring)
1259 (*env)->CallObjectMethod(env, jClassObject, jMethod);
1260 assert(jClassNameString != 0);
1261 classNameString = (char*)
1262 (*env)->GetStringUTFChars(env, jClassNameString, NULL);
1263 if (classNameString == NULL) { return NULL; }
1264 exceptionMsgPrefix = "Java object of this class cannot be converted to native PKCS#11 type: ";
1265 exceptionMsg = (char *)
1266 malloc(strlen(exceptionMsgPrefix) + strlen(classNameString) + 1);
1267 if (exceptionMsg == NULL) {
1268 (*env)->ReleaseStringUTFChars(env, jClassNameString, classNameString);
1269 throwOutOfMemoryError(env, 0);
1270 return NULL;
1271 }
1272 strcpy(exceptionMsg, exceptionMsgPrefix);
1273 strcat(exceptionMsg, classNameString);
1274 (*env)->ReleaseStringUTFChars(env, jClassNameString, classNameString);
1275 throwPKCS11RuntimeException(env, exceptionMsg);
1276 free(exceptionMsg);
1277 *ckpLength = 0;
1278
1279 TRACE0("FINISHED\n");
1280 return NULL;
1281 }
1282
1283 #ifdef P11_MEMORYDEBUG
1284
1285 #undef malloc
1286 #undef calloc
1287 #undef free
1288
p11malloc(size_t c,char * file,int line)1289 void *p11malloc(size_t c, char *file, int line) {
1290 void *p = malloc(c);
1291 fprintf(stdout, "malloc\t%08lX\t%lX\t%s:%d\n", ptr_to_jlong(p), c, file, line);
1292 fflush(stdout);
1293 return p;
1294 }
1295
p11calloc(size_t c,size_t s,char * file,int line)1296 void *p11calloc(size_t c, size_t s, char *file, int line) {
1297 void *p = calloc(c, s);
1298 fprintf(stdout, "calloc\t%08lX\t%lX\t%lX\t%s:%d\n", ptr_to_jlong(p), c, s, file, line);
1299 fflush(stdout);
1300 return p;
1301 }
1302
p11free(void * p,char * file,int line)1303 void p11free(void *p, char *file, int line) {
1304 fprintf(stdout, "free\t%08lX\t\t%s:%d\n", ptr_to_jlong(p), file, line);
1305 fflush(stdout);
1306 free(p);
1307 }
1308
1309 #endif
1310
1311 // prints a message to stdout if debug output is enabled
printDebug(const char * format,...)1312 void printDebug(const char *format, ...) {
1313 if (debug == JNI_TRUE) {
1314 va_list args;
1315 fprintf(stdout, "sunpkcs11: ");
1316 va_start(args, format);
1317 vfprintf(stdout, format, args);
1318 va_end(args);
1319 fflush(stdout);
1320 }
1321 }
1322
1323