blob: 31674f4ef9cd2e62b65260d1e6a160bc698111ee [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Portions Copyright 2003 Sun Microsystems, Inc. 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#include "sun_security_pkcs11_wrapper_PKCS11.h"
56
57/* The initArgs that enable the application to do custom mutex-handling */
58#ifndef NO_CALLBACKS
59jobject jInitArgsObject;
60CK_C_INITIALIZE_ARGS_PTR ckpGlobalInitArgs;
61#endif /* NO_CALLBACKS */
62
63/* ************************************************************************** */
64/* Now come the functions for mutex handling and notification callbacks */
65/* ************************************************************************** */
66
67/*
68 * converts the InitArgs object to a CK_C_INITIALIZE_ARGS structure and sets the functions
69 * that will call the right Java mutex functions
70 *
71 * @param env - used to call JNI funktions to get the Java classes, objects, methods and fields
72 * @param pInitArgs - the InitArgs object with the Java mutex functions to call
73 * @return - the pointer to the CK_C_INITIALIZE_ARGS structure with the functions that will call
74 * the corresponding Java functions
75 */
76CK_C_INITIALIZE_ARGS_PTR makeCKInitArgsAdapter(JNIEnv *env, jobject jInitArgs)
77{
78 CK_C_INITIALIZE_ARGS_PTR ckpInitArgs;
79 jclass jInitArgsClass = (*env)->FindClass(env, CLASS_C_INITIALIZE_ARGS);
80 jfieldID fieldID;
81 jlong jFlags;
82 jobject jReserved;
83 CK_ULONG ckReservedLength;
84#ifndef NO_CALLBACKS
85 jobject jMutexHandler;
86#endif /* NO_CALLBACKS */
87
88 if(jInitArgs == NULL) {
89 return NULL_PTR;
90 }
91
92 /* convert the Java InitArgs object to a pointer to a CK_C_INITIALIZE_ARGS structure */
93 ckpInitArgs = (CK_C_INITIALIZE_ARGS_PTR) malloc(sizeof(CK_C_INITIALIZE_ARGS));
94
95 /* Set the mutex functions that will call the Java mutex functions, but
96 * only set it, if the field is not null.
97 */
98#ifdef NO_CALLBACKS
99 ckpInitArgs->CreateMutex = NULL_PTR;
100 ckpInitArgs->DestroyMutex = NULL_PTR;
101 ckpInitArgs->LockMutex = NULL_PTR;
102 ckpInitArgs->UnlockMutex = NULL_PTR;
103#else
104 fieldID = (*env)->GetFieldID(env, jInitArgsClass, "CreateMutex", "Lsun/security/pkcs11/wrapper/CK_CREATEMUTEX;");
105 assert(fieldID != 0);
106 jMutexHandler = (*env)->GetObjectField(env, jInitArgs, fieldID);
107 ckpInitArgs->CreateMutex = (jMutexHandler != NULL) ? &callJCreateMutex : NULL_PTR;
108
109 fieldID = (*env)->GetFieldID(env, jInitArgsClass, "DestroyMutex", "Lsun/security/pkcs11/wrapper/CK_DESTROYMUTEX;");
110 assert(fieldID != 0);
111 jMutexHandler = (*env)->GetObjectField(env, jInitArgs, fieldID);
112 ckpInitArgs->DestroyMutex = (jMutexHandler != NULL) ? &callJDestroyMutex : NULL_PTR;
113
114 fieldID = (*env)->GetFieldID(env, jInitArgsClass, "LockMutex", "Lsun/security/pkcs11/wrapper/CK_LOCKMUTEX;");
115 assert(fieldID != 0);
116 jMutexHandler = (*env)->GetObjectField(env, jInitArgs, fieldID);
117 ckpInitArgs->LockMutex = (jMutexHandler != NULL) ? &callJLockMutex : NULL_PTR;
118
119 fieldID = (*env)->GetFieldID(env, jInitArgsClass, "UnlockMutex", "Lsun/security/pkcs11/wrapper/CK_UNLOCKMUTEX;");
120 assert(fieldID != 0);
121 jMutexHandler = (*env)->GetObjectField(env, jInitArgs, fieldID);
122 ckpInitArgs->UnlockMutex = (jMutexHandler != NULL) ? &callJUnlockMutex : NULL_PTR;
123
124 if ((ckpInitArgs->CreateMutex != NULL_PTR)
125 || (ckpInitArgs->DestroyMutex != NULL_PTR)
126 || (ckpInitArgs->LockMutex != NULL_PTR)
127 || (ckpInitArgs->UnlockMutex != NULL_PTR)) {
128 /* we only need to keep a global copy, if we need callbacks */
129 /* set the global object jInitArgs so that the right Java mutex functions will be called */
130 jInitArgsObject = (*env)->NewGlobalRef(env, jInitArgs);
131 ckpGlobalInitArgs = (CK_C_INITIALIZE_ARGS_PTR) malloc(sizeof(CK_C_INITIALIZE_ARGS));
132 memcpy(ckpGlobalInitArgs, ckpInitArgs, sizeof(CK_C_INITIALIZE_ARGS));
133 }
134#endif /* NO_CALLBACKS */
135
136 /* convert and set the flags field */
137 fieldID = (*env)->GetFieldID(env, jInitArgsClass, "flags", "J");
138 assert(fieldID != 0);
139 jFlags = (*env)->GetLongField(env, jInitArgs, fieldID);
140 ckpInitArgs->flags = jLongToCKULong(jFlags);
141
142 /* pReserved should be NULL_PTR in this version */
143 fieldID = (*env)->GetFieldID(env, jInitArgsClass, "pReserved", "Ljava/lang/Object;");
144 assert(fieldID != 0);
145 jReserved = (*env)->GetObjectField(env, jInitArgs, fieldID);
146
147 /* we try to convert the reserved parameter also */
148 jObjectToPrimitiveCKObjectPtrPtr(env, jReserved, &(ckpInitArgs->pReserved), &ckReservedLength);
149
150 return ckpInitArgs ;
151}
152
153#ifndef NO_CALLBACKS
154
155/*
156 * is the function that gets called by PKCS#11 to create a mutex and calls the Java
157 * CreateMutex function
158 *
159 * @param env - used to call JNI funktions to get the Java classes, objects, methods and fields
160 * @param ppMutex - the new created mutex
161 * @return - should return CKR_OK if the mutex creation was ok
162 */
163CK_RV callJCreateMutex(CK_VOID_PTR_PTR ppMutex)
164{
165 JavaVM *jvm;
166 JNIEnv *env;
167 jsize actualNumberVMs;
168 jint returnValue;
169 jthrowable pkcs11Exception;
170 jclass pkcs11ExceptionClass;
171 jlong errorCode;
172 CK_RV rv = CKR_OK;
173 int wasAttached = 1;
174 jclass jCreateMutexClass;
175 jclass jInitArgsClass;
176 jmethodID methodID;
177 jfieldID fieldID;
178 jobject jCreateMutex;
179 jobject jMutex;
180
181
182 /* Get the currently running Java VM */
183 returnValue = JNI_GetCreatedJavaVMs(&jvm, (jsize) 1, &actualNumberVMs);
184 if ((returnValue != 0) || (actualNumberVMs <= 0)) { return rv ;} /* there is no VM running */
185
186 /* Determine, if current thread is already attached */
187 returnValue = (*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION_1_2);
188 if (returnValue == JNI_EDETACHED) {
189 /* thread detached, so attach it */
190 wasAttached = 0;
191 returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL);
192 } else if (returnValue == JNI_EVERSION) {
193 /* this version of JNI is not supported, so just try to attach */
194 /* we assume it was attached to ensure that this thread is not detached
195 * afterwards even though it should not
196 */
197 wasAttached = 1;
198 returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL);
199 } else {
200 /* attached */
201 wasAttached = 1;
202 }
203
204
205 jCreateMutexClass = (*env)->FindClass(env, CLASS_CREATEMUTEX);
206 jInitArgsClass = (*env)->FindClass(env, CLASS_C_INITIALIZE_ARGS);
207
208 /* get the CreateMutex object out of the jInitArgs object */
209 fieldID = (*env)->GetFieldID(env, jInitArgsClass, "CreateMutex", "Lsun/security/pkcs11/wrapper/CK_CREATEMUTEX;");
210 assert(fieldID != 0);
211 jCreateMutex = (*env)->GetObjectField(env, jInitArgsObject, fieldID);
212 assert(jCreateMutex != 0);
213
214 /* call the CK_CREATEMUTEX function of the CreateMutex object */
215 /* and get the new Java mutex object */
216 methodID = (*env)->GetMethodID(env, jCreateMutexClass, "CK_CREATEMUTEX", "()Ljava/lang/Object;");
217 assert(methodID != 0);
218 jMutex = (*env)->CallObjectMethod(env, jCreateMutex, methodID);
219
220 /* set a global reference on the Java mutex */
221 jMutex = (*env)->NewGlobalRef(env, jMutex);
222 /* convert the Java mutex to a CK mutex */
223 *ppMutex = jObjectToCKVoidPtr(jMutex);
224
225
226 /* check, if callback threw an exception */
227 pkcs11Exception = (*env)->ExceptionOccurred(env);
228
229 if (pkcs11Exception != NULL) {
230 /* The was an exception thrown, now we get the error-code from it */
231 pkcs11ExceptionClass = (*env)->FindClass(env, CLASS_PKCS11EXCEPTION);
232 methodID = (*env)->GetMethodID(env, pkcs11ExceptionClass, "getErrorCode", "()J");
233 assert(methodID != 0);
234 errorCode = (*env)->CallLongMethod(env, pkcs11Exception, methodID);
235 rv = jLongToCKULong(errorCode);
236 }
237
238 /* if we attached this thread to the VM just for callback, we detach it now */
239 if (wasAttached) {
240 returnValue = (*jvm)->DetachCurrentThread(jvm);
241 }
242
243 return rv ;
244}
245
246/*
247 * is the function that gets called by PKCS#11 to destroy a mutex and calls the Java
248 * DestroyMutex function
249 *
250 * @param env - used to call JNI funktions to get the Java classes, objects, methods and fields
251 * @param pMutex - the mutex to destroy
252 * @return - should return CKR_OK if the mutex was destroyed
253 */
254CK_RV callJDestroyMutex(CK_VOID_PTR pMutex)
255{
256 JavaVM *jvm;
257 JNIEnv *env;
258 jsize actualNumberVMs;
259 jint returnValue;
260 jthrowable pkcs11Exception;
261 jclass pkcs11ExceptionClass;
262 jlong errorCode;
263 CK_RV rv = CKR_OK;
264 int wasAttached = 1;
265 jclass jDestroyMutexClass;
266 jclass jInitArgsClass;
267 jmethodID methodID;
268 jfieldID fieldID;
269 jobject jDestroyMutex;
270 jobject jMutex;
271
272
273 /* Get the currently running Java VM */
274 returnValue = JNI_GetCreatedJavaVMs(&jvm, (jsize) 1, &actualNumberVMs);
275 if ((returnValue != 0) || (actualNumberVMs <= 0)) { return rv ; } /* there is no VM running */
276
277 /* Determine, if current thread is already attached */
278 returnValue = (*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION_1_2);
279 if (returnValue == JNI_EDETACHED) {
280 /* thread detached, so attach it */
281 wasAttached = 0;
282 returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL);
283 } else if (returnValue == JNI_EVERSION) {
284 /* this version of JNI is not supported, so just try to attach */
285 /* we assume it was attached to ensure that this thread is not detached
286 * afterwards even though it should not
287 */
288 wasAttached = 1;
289 returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL);
290 } else {
291 /* attached */
292 wasAttached = 1;
293 }
294
295
296 jDestroyMutexClass = (*env)->FindClass(env, CLASS_DESTROYMUTEX);
297 jInitArgsClass = (*env)->FindClass(env, CLASS_C_INITIALIZE_ARGS);
298
299 /* convert the CK mutex to a Java mutex */
300 jMutex = ckVoidPtrToJObject(pMutex);
301
302 /* get the DestroyMutex object out of the jInitArgs object */
303 fieldID = (*env)->GetFieldID(env, jInitArgsClass, "DestroyMutex", "Lsun/security/pkcs11/wrapper/CK_DESTROYMUTEX;");
304 assert(fieldID != 0);
305 jDestroyMutex = (*env)->GetObjectField(env, jInitArgsObject, fieldID);
306 assert(jDestroyMutex != 0);
307
308 /* call the CK_DESTROYMUTEX method of the DestroyMutex object */
309 methodID = (*env)->GetMethodID(env, jDestroyMutexClass, "CK_DESTROYMUTEX", "(Ljava/lang/Object;)V");
310 assert(methodID != 0);
311 (*env)->CallVoidMethod(env, jDestroyMutex, methodID, jMutex);
312
313 /* delete the global reference on the Java mutex */
314 (*env)->DeleteGlobalRef(env, jMutex);
315
316
317 /* check, if callback threw an exception */
318 pkcs11Exception = (*env)->ExceptionOccurred(env);
319
320 if (pkcs11Exception != NULL) {
321 /* The was an exception thrown, now we get the error-code from it */
322 pkcs11ExceptionClass = (*env)->FindClass(env, CLASS_PKCS11EXCEPTION);
323 methodID = (*env)->GetMethodID(env, pkcs11ExceptionClass, "getErrorCode", "()J");
324 assert(methodID != 0);
325 errorCode = (*env)->CallLongMethod(env, pkcs11Exception, methodID);
326 rv = jLongToCKULong(errorCode);
327 }
328
329 /* if we attached this thread to the VM just for callback, we detach it now */
330 if (wasAttached) {
331 returnValue = (*jvm)->DetachCurrentThread(jvm);
332 }
333
334 return rv ;
335}
336
337/*
338 * is the function that gets called by PKCS#11 to lock a mutex and calls the Java
339 * LockMutex function
340 *
341 * @param env - used to call JNI funktions to get the Java classes, objects, methods and fields
342 * @param pMutex - the mutex to lock
343 * @return - should return CKR_OK if the mutex was not locked already
344 */
345CK_RV callJLockMutex(CK_VOID_PTR pMutex)
346{
347 JavaVM *jvm;
348 JNIEnv *env;
349 jsize actualNumberVMs;
350 jint returnValue;
351 jthrowable pkcs11Exception;
352 jclass pkcs11ExceptionClass;
353 jlong errorCode;
354 CK_RV rv = CKR_OK;
355 int wasAttached = 1;
356 jclass jLockMutexClass;
357 jclass jInitArgsClass;
358 jmethodID methodID;
359 jfieldID fieldID;
360 jobject jLockMutex;
361 jobject jMutex;
362
363
364 /* Get the currently running Java VM */
365 returnValue = JNI_GetCreatedJavaVMs(&jvm, (jsize) 1, &actualNumberVMs);
366 if ((returnValue != 0) || (actualNumberVMs <= 0)) { return rv ; } /* there is no VM running */
367
368 /* Determine, if current thread is already attached */
369 returnValue = (*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION_1_2);
370 if (returnValue == JNI_EDETACHED) {
371 /* thread detached, so attach it */
372 wasAttached = 0;
373 returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL);
374 } else if (returnValue == JNI_EVERSION) {
375 /* this version of JNI is not supported, so just try to attach */
376 /* we assume it was attached to ensure that this thread is not detached
377 * afterwards even though it should not
378 */
379 wasAttached = 1;
380 returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL);
381 } else {
382 /* attached */
383 wasAttached = 1;
384 }
385
386
387 jLockMutexClass = (*env)->FindClass(env, CLASS_LOCKMUTEX);
388 jInitArgsClass = (*env)->FindClass(env, CLASS_C_INITIALIZE_ARGS);
389
390 /* convert the CK mutex to a Java mutex */
391 jMutex = ckVoidPtrToJObject(pMutex);
392
393 /* get the LockMutex object out of the jInitArgs object */
394 fieldID = (*env)->GetFieldID(env, jInitArgsClass, "LockMutex", "Lsun/security/pkcs11/wrapper/CK_LOCKMUTEX;");
395 assert(fieldID != 0);
396 jLockMutex = (*env)->GetObjectField(env, jInitArgsObject, fieldID);
397 assert(jLockMutex != 0);
398
399 /* call the CK_LOCKMUTEX method of the LockMutex object */
400 methodID = (*env)->GetMethodID(env, jLockMutexClass, "CK_LOCKMUTEX", "(Ljava/lang/Object;)V");
401 assert(methodID != 0);
402 (*env)->CallVoidMethod(env, jLockMutex, methodID, jMutex);
403
404
405 /* check, if callback threw an exception */
406 pkcs11Exception = (*env)->ExceptionOccurred(env);
407
408 if (pkcs11Exception != NULL) {
409 /* The was an exception thrown, now we get the error-code from it */
410 pkcs11ExceptionClass = (*env)->FindClass(env, CLASS_PKCS11EXCEPTION);
411 methodID = (*env)->GetMethodID(env, pkcs11ExceptionClass, "getErrorCode", "()J");
412 assert(methodID != 0);
413 errorCode = (*env)->CallLongMethod(env, pkcs11Exception, methodID);
414 rv = jLongToCKULong(errorCode);
415 }
416
417 /* if we attached this thread to the VM just for callback, we detach it now */
418 if (wasAttached) {
419 returnValue = (*jvm)->DetachCurrentThread(jvm);
420 }
421
422 return rv ;
423}
424
425/*
426 * is the function that gets called by PKCS#11 to unlock a mutex and calls the Java
427 * UnlockMutex function
428 *
429 * @param env - used to call JNI funktions to get the Java classes, objects, methods and fields
430 * @param pMutex - the mutex to unlock
431 * @return - should return CKR_OK if the mutex was not unlocked already
432 */
433CK_RV callJUnlockMutex(CK_VOID_PTR pMutex)
434{
435 JavaVM *jvm;
436 JNIEnv *env;
437 jsize actualNumberVMs;
438 jint returnValue;
439 jthrowable pkcs11Exception;
440 jclass pkcs11ExceptionClass;
441 jlong errorCode;
442 CK_RV rv = CKR_OK;
443 int wasAttached = 1;
444 jclass jUnlockMutexClass;
445 jclass jInitArgsClass;
446 jmethodID methodID;
447 jfieldID fieldID;
448 jobject jUnlockMutex;
449 jobject jMutex;
450
451
452 /* Get the currently running Java VM */
453 returnValue = JNI_GetCreatedJavaVMs(&jvm, (jsize) 1, &actualNumberVMs);
454 if ((returnValue != 0) || (actualNumberVMs <= 0)) { return rv ; } /* there is no VM running */
455
456 /* Determine, if current thread is already attached */
457 returnValue = (*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION_1_2);
458 if (returnValue == JNI_EDETACHED) {
459 /* thread detached, so attach it */
460 wasAttached = 0;
461 returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL);
462 } else if (returnValue == JNI_EVERSION) {
463 /* this version of JNI is not supported, so just try to attach */
464 /* we assume it was attached to ensure that this thread is not detached
465 * afterwards even though it should not
466 */
467 wasAttached = 1;
468 returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL);
469 } else {
470 /* attached */
471 wasAttached = 1;
472 }
473
474
475 jUnlockMutexClass = (*env)->FindClass(env, CLASS_UNLOCKMUTEX);
476 jInitArgsClass = (*env)->FindClass(env, CLASS_C_INITIALIZE_ARGS);
477
478 /* convert the CK-type mutex to a Java mutex */
479 jMutex = ckVoidPtrToJObject(pMutex);
480
481 /* get the UnlockMutex object out of the jInitArgs object */
482 fieldID = (*env)->GetFieldID(env, jInitArgsClass, "UnlockMutex", "Lsun/security/pkcs11/wrapper/CK_UNLOCKMUTEX;");
483 assert(fieldID != 0);
484 jUnlockMutex = (*env)->GetObjectField(env, jInitArgsObject, fieldID);
485 assert(jUnlockMutex != 0);
486
487 /* call the CK_UNLOCKMUTEX method of the UnLockMutex object */
488 methodID = (*env)->GetMethodID(env, jUnlockMutexClass, "CK_UNLOCKMUTEX", "(Ljava/lang/Object;)V");
489 assert(methodID != 0);
490 (*env)->CallVoidMethod(env, jUnlockMutex, methodID, jMutex);
491
492
493 /* check, if callback threw an exception */
494 pkcs11Exception = (*env)->ExceptionOccurred(env);
495
496 if (pkcs11Exception != NULL) {
497 /* The was an exception thrown, now we get the error-code from it */
498 pkcs11ExceptionClass = (*env)->FindClass(env, CLASS_PKCS11EXCEPTION);
499 methodID = (*env)->GetMethodID(env, pkcs11ExceptionClass, "getErrorCode", "()J");
500 assert(methodID != 0);
501 errorCode = (*env)->CallLongMethod(env, pkcs11Exception, methodID);
502 rv = jLongToCKULong(errorCode);
503 }
504
505 /* if we attached this thread to the VM just for callback, we detach it now */
506 if (wasAttached) {
507 returnValue = (*jvm)->DetachCurrentThread(jvm);
508 }
509
510 return rv ;
511}
512
513#endif /* NO_CALLBACKS */