Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_sessmgmt.c
41149 views
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
#include "sun_security_pkcs11_wrapper_PKCS11.h"
56
57
/* The list of notify callback handles that are currently active and waiting
58
* for callbacks from their sessions.
59
*/
60
#ifndef NO_CALLBACKS
61
NotifyListNode *notifyListHead = NULL;
62
jobject notifyListLock = NULL;
63
#endif /* NO_CALLBACKS */
64
65
#ifdef P11_ENABLE_C_OPENSESSION
66
/*
67
* Class: sun_security_pkcs11_wrapper_PKCS11
68
* Method: C_OpenSession
69
* Signature: (JJLjava/lang/Object;Lsun/security/pkcs11/wrapper/CK_NOTIFY;)J
70
* Parametermapping: *PKCS11*
71
* @param jlong jSlotID CK_SLOT_ID slotID
72
* @param jlong jFlags CK_FLAGS flags
73
* @param jobject jApplication CK_VOID_PTR pApplication
74
* @param jobject jNotify CK_NOTIFY Notify
75
* @return jlong jSessionHandle CK_SESSION_HANDLE_PTR phSession
76
*/
77
JNIEXPORT jlong JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1OpenSession
78
(JNIEnv *env, jobject obj, jlong jSlotID, jlong jFlags, jobject jApplication, jobject jNotify)
79
{
80
CK_SESSION_HANDLE ckSessionHandle;
81
CK_SLOT_ID ckSlotID;
82
CK_FLAGS ckFlags;
83
CK_VOID_PTR ckpApplication;
84
CK_NOTIFY ckNotify;
85
jlong jSessionHandle;
86
CK_RV rv;
87
#ifndef NO_CALLBACKS
88
NotifyEncapsulation *notifyEncapsulation = NULL;
89
#endif /* NO_CALLBACKS */
90
91
CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
92
if (ckpFunctions == NULL) { return 0L; }
93
94
ckSlotID = jLongToCKULong(jSlotID);
95
ckFlags = jLongToCKULong(jFlags);
96
97
#ifndef NO_CALLBACKS
98
if (jNotify != NULL) {
99
notifyEncapsulation = (NotifyEncapsulation *) malloc(sizeof(NotifyEncapsulation));
100
if (notifyEncapsulation == NULL) {
101
throwOutOfMemoryError(env, 0);
102
return 0L;
103
}
104
notifyEncapsulation->jApplicationData = (jApplication != NULL)
105
? (*env)->NewGlobalRef(env, jApplication)
106
: NULL;
107
notifyEncapsulation->jNotifyObject = (*env)->NewGlobalRef(env, jNotify);
108
ckpApplication = notifyEncapsulation;
109
ckNotify = (CK_NOTIFY) &notifyCallback;
110
} else {
111
ckpApplication = NULL_PTR;
112
ckNotify = NULL_PTR;
113
}
114
#else
115
ckpApplication = NULL_PTR;
116
ckNotify = NULL_PTR;
117
#endif /* NO_CALLBACKS */
118
119
TRACE0("DEBUG: C_OpenSession");
120
TRACE1(", slotID=%lu", ckSlotID);
121
TRACE1(", flags=%lu", (unsigned long) ckFlags);
122
TRACE0(" ... ");
123
124
rv = (*ckpFunctions->C_OpenSession)(ckSlotID, ckFlags, ckpApplication, ckNotify, &ckSessionHandle);
125
if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) {
126
#ifndef NO_CALLBACKS
127
if (notifyEncapsulation != NULL) {
128
if (notifyEncapsulation->jApplicationData != NULL) {
129
(*env)->DeleteGlobalRef(env, jApplication);
130
}
131
(*env)->DeleteGlobalRef(env, jNotify);
132
free(notifyEncapsulation);
133
}
134
#endif /* NO_CALLBACKS */
135
return 0L;
136
}
137
138
TRACE0("got session");
139
TRACE1(", SessionHandle=%lu", (unsigned long) ckSessionHandle);
140
TRACE0(" ... ");
141
142
jSessionHandle = ckULongToJLong(ckSessionHandle);
143
144
#ifndef NO_CALLBACKS
145
if (notifyEncapsulation != NULL) {
146
/* store the notifyEncapsulation to enable later cleanup */
147
putNotifyEntry(env, ckSessionHandle, notifyEncapsulation);
148
}
149
#endif /* NO_CALLBACKS */
150
151
TRACE0("FINISHED\n");
152
153
return jSessionHandle ;
154
}
155
#endif
156
157
#ifdef P11_ENABLE_C_CLOSESESSION
158
/*
159
* Class: sun_security_pkcs11_wrapper_PKCS11
160
* Method: C_CloseSession
161
* Signature: (J)V
162
* Parametermapping: *PKCS11*
163
* @param jlong jSessionHandle CK_SESSION_HANDLE hSession
164
*/
165
JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1CloseSession
166
(JNIEnv *env, jobject obj, jlong jSessionHandle)
167
{
168
CK_SESSION_HANDLE ckSessionHandle;
169
CK_RV rv;
170
#ifndef NO_CALLBACKS
171
NotifyEncapsulation *notifyEncapsulation;
172
jobject jApplicationData;
173
#endif /* NO_CALLBACKS */
174
175
CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
176
if (ckpFunctions == NULL) { return; }
177
178
ckSessionHandle = jLongToCKULong(jSessionHandle);
179
180
rv = (*ckpFunctions->C_CloseSession)(ckSessionHandle);
181
if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; }
182
183
#ifndef NO_CALLBACKS
184
notifyEncapsulation = removeNotifyEntry(env, ckSessionHandle);
185
186
if (notifyEncapsulation != NULL) {
187
/* there was a notify object used with this session, now dump the
188
* encapsulation object
189
*/
190
(*env)->DeleteGlobalRef(env, notifyEncapsulation->jNotifyObject);
191
jApplicationData = notifyEncapsulation->jApplicationData;
192
if (jApplicationData != NULL) {
193
(*env)->DeleteGlobalRef(env, jApplicationData);
194
}
195
free(notifyEncapsulation);
196
}
197
#endif /* NO_CALLBACKS */
198
199
}
200
#endif
201
202
#ifdef P11_ENABLE_C_CLOSEALLSESSIONS
203
/*
204
* Class: sun_security_pkcs11_wrapper_PKCS11
205
* Method: C_CloseAllSessions
206
* Signature: (J)V
207
* Parametermapping: *PKCS11*
208
* @param jlong jSlotID CK_SLOT_ID slotID
209
*/
210
JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1CloseAllSessions
211
(JNIEnv *env, jobject obj, jlong jSlotID)
212
{
213
CK_SLOT_ID ckSlotID;
214
CK_RV rv;
215
#ifndef NO_CALLBACKS
216
NotifyEncapsulation *notifyEncapsulation;
217
jobject jApplicationData;
218
#endif /* NO_CALLBACKS */
219
220
CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
221
if (ckpFunctions == NULL) { return; }
222
223
ckSlotID = jLongToCKULong(jSlotID);
224
225
rv = (*ckpFunctions->C_CloseAllSessions)(ckSlotID);
226
if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; }
227
228
#ifndef NO_CALLBACKS
229
/* Remove all notify callback helper objects. */
230
while ((notifyEncapsulation = removeFirstNotifyEntry(env)) != NULL) {
231
/* there was a notify object used with this session, now dump the
232
* encapsulation object
233
*/
234
(*env)->DeleteGlobalRef(env, notifyEncapsulation->jNotifyObject);
235
jApplicationData = notifyEncapsulation->jApplicationData;
236
if (jApplicationData != NULL) {
237
(*env)->DeleteGlobalRef(env, jApplicationData);
238
}
239
free(notifyEncapsulation);
240
}
241
#endif /* NO_CALLBACKS */
242
}
243
#endif
244
245
#ifdef P11_ENABLE_C_GETSESSIONINFO
246
/*
247
* Class: sun_security_pkcs11_wrapper_PKCS11
248
* Method: C_GetSessionInfo
249
* Signature: (J)Lsun/security/pkcs11/wrapper/CK_SESSION_INFO;
250
* Parametermapping: *PKCS11*
251
* @param jlong jSessionHandle CK_SESSION_HANDLE hSession
252
* @return jobject jSessionInfo CK_SESSION_INFO_PTR pInfo
253
*/
254
JNIEXPORT jobject JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1GetSessionInfo
255
(JNIEnv *env, jobject obj, jlong jSessionHandle)
256
{
257
CK_SESSION_HANDLE ckSessionHandle;
258
CK_SESSION_INFO ckSessionInfo;
259
jobject jSessionInfo=NULL;
260
CK_RV rv;
261
262
CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
263
if (ckpFunctions == NULL) { return NULL; }
264
265
ckSessionHandle = jLongToCKULong(jSessionHandle);
266
267
rv = (*ckpFunctions->C_GetSessionInfo)(ckSessionHandle, &ckSessionInfo);
268
if (ckAssertReturnValueOK(env, rv) == CK_ASSERT_OK) {
269
jSessionInfo = ckSessionInfoPtrToJSessionInfo(env, &ckSessionInfo);
270
}
271
return jSessionInfo ;
272
}
273
#endif
274
275
#ifdef P11_ENABLE_C_GETOPERATIONSTATE
276
/*
277
* Class: sun_security_pkcs11_wrapper_PKCS11
278
* Method: C_GetOperationState
279
* Signature: (J)[B
280
* Parametermapping: *PKCS11*
281
* @param jlong jSessionHandle CK_SESSION_HANDLE hSession
282
* @return jbyteArray jState CK_BYTE_PTR pOperationState
283
* CK_ULONG_PTR pulOperationStateLen
284
*/
285
JNIEXPORT jbyteArray JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1GetOperationState
286
(JNIEnv *env, jobject obj, jlong jSessionHandle)
287
{
288
CK_SESSION_HANDLE ckSessionHandle;
289
CK_BYTE_PTR ckpState;
290
CK_ULONG ckStateLength;
291
jbyteArray jState = NULL;
292
CK_RV rv;
293
294
CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
295
if (ckpFunctions == NULL) { return NULL; }
296
297
ckSessionHandle = jLongToCKULong(jSessionHandle);
298
299
rv = (*ckpFunctions->C_GetOperationState)(ckSessionHandle, NULL_PTR, &ckStateLength);
300
if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return NULL ; }
301
302
ckpState = (CK_BYTE_PTR) malloc(ckStateLength);
303
if (ckpState == NULL) {
304
throwOutOfMemoryError(env, 0);
305
return NULL;
306
}
307
308
rv = (*ckpFunctions->C_GetOperationState)(ckSessionHandle, ckpState, &ckStateLength);
309
if (ckAssertReturnValueOK(env, rv) == CK_ASSERT_OK) {
310
jState = ckByteArrayToJByteArray(env, ckpState, ckStateLength);
311
}
312
free(ckpState);
313
314
return jState ;
315
}
316
#endif
317
318
#ifdef P11_ENABLE_C_SETOPERATIONSTATE
319
/*
320
* Class: sun_security_pkcs11_wrapper_PKCS11
321
* Method: C_SetOperationState
322
* Signature: (J[BJJ)V
323
* Parametermapping: *PKCS11*
324
* @param jlong jSessionHandle CK_SESSION_HANDLE hSession
325
* @param jbyteArray jOperationState CK_BYTE_PTR pOperationState
326
* CK_ULONG ulOperationStateLen
327
* @param jlong jEncryptionKeyHandle CK_OBJECT_HANDLE hEncryptionKey
328
* @param jlong jAuthenticationKeyHandle CK_OBJECT_HANDLE hAuthenticationKey
329
*/
330
JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1SetOperationState
331
(JNIEnv *env, jobject obj, jlong jSessionHandle, jbyteArray jOperationState, jlong jEncryptionKeyHandle, jlong jAuthenticationKeyHandle)
332
{
333
CK_SESSION_HANDLE ckSessionHandle;
334
CK_BYTE_PTR ckpState = NULL_PTR;
335
CK_ULONG ckStateLength;
336
CK_OBJECT_HANDLE ckEncryptionKeyHandle;
337
CK_OBJECT_HANDLE ckAuthenticationKeyHandle;
338
CK_RV rv;
339
340
CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
341
if (ckpFunctions == NULL) { return; }
342
343
ckSessionHandle = jLongToCKULong(jSessionHandle);
344
jByteArrayToCKByteArray(env, jOperationState, &ckpState, &ckStateLength);
345
if ((*env)->ExceptionCheck(env)) { return; }
346
347
ckEncryptionKeyHandle = jLongToCKULong(jEncryptionKeyHandle);
348
ckAuthenticationKeyHandle = jLongToCKULong(jAuthenticationKeyHandle);
349
350
rv = (*ckpFunctions->C_SetOperationState)(ckSessionHandle, ckpState, ckStateLength, ckEncryptionKeyHandle, ckAuthenticationKeyHandle);
351
352
free(ckpState);
353
354
if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; }
355
}
356
#endif
357
358
#ifdef P11_ENABLE_C_LOGIN
359
/*
360
* Class: sun_security_pkcs11_wrapper_PKCS11
361
* Method: C_Login
362
* Signature: (JJ[C)V
363
* Parametermapping: *PKCS11*
364
* @param jlong jSessionHandle CK_SESSION_HANDLE hSession
365
* @param jlong jUserType CK_USER_TYPE userType
366
* @param jcharArray jPin CK_CHAR_PTR pPin
367
* CK_ULONG ulPinLen
368
*/
369
JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1Login
370
(JNIEnv *env, jobject obj, jlong jSessionHandle, jlong jUserType, jcharArray jPin)
371
{
372
CK_SESSION_HANDLE ckSessionHandle;
373
CK_USER_TYPE ckUserType;
374
CK_CHAR_PTR ckpPinArray = NULL_PTR;
375
CK_ULONG ckPinLength;
376
CK_RV rv;
377
378
CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
379
if (ckpFunctions == NULL) { return; }
380
381
ckSessionHandle = jLongToCKULong(jSessionHandle);
382
ckUserType = jLongToCKULong(jUserType);
383
jCharArrayToCKCharArray(env, jPin, &ckpPinArray, &ckPinLength);
384
if ((*env)->ExceptionCheck(env)) { return; }
385
386
rv = (*ckpFunctions->C_Login)(ckSessionHandle, ckUserType, ckpPinArray, ckPinLength);
387
388
free(ckpPinArray);
389
390
if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; }
391
}
392
#endif
393
394
#ifdef P11_ENABLE_C_LOGOUT
395
/*
396
* Class: sun_security_pkcs11_wrapper_PKCS11
397
* Method: C_Logout
398
* Signature: (J)V
399
* Parametermapping: *PKCS11*
400
* @param jlong jSessionHandle CK_SESSION_HANDLE hSession
401
*/
402
JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1Logout
403
(JNIEnv *env, jobject obj, jlong jSessionHandle)
404
{
405
CK_SESSION_HANDLE ckSessionHandle;
406
CK_RV rv;
407
408
CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
409
if (ckpFunctions == NULL) { return; }
410
411
ckSessionHandle = jLongToCKULong(jSessionHandle);
412
413
rv = (*ckpFunctions->C_Logout)(ckSessionHandle);
414
if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; }
415
}
416
#endif
417
418
/* ************************************************************************** */
419
/* Functions for keeping track of notify callbacks */
420
/* ************************************************************************** */
421
422
#ifndef NO_CALLBACKS
423
424
/*
425
* Add the given notify encapsulation object to the list of active notify
426
* objects.
427
* If notifyEncapsulation is NULL, this function does nothing.
428
*/
429
void putNotifyEntry(JNIEnv *env, CK_SESSION_HANDLE hSession, NotifyEncapsulation *notifyEncapsulation) {
430
NotifyListNode *currentNode, *newNode;
431
432
if (notifyEncapsulation == NULL) {
433
return;
434
}
435
436
newNode = (NotifyListNode *) malloc(sizeof(NotifyListNode));
437
if (newNode == NULL) {
438
throwOutOfMemoryError(env, 0);
439
return;
440
}
441
newNode->hSession = hSession;
442
newNode->notifyEncapsulation = notifyEncapsulation;
443
newNode->next = NULL;
444
445
(*env)->MonitorEnter(env, notifyListLock); /* synchronize access to list */
446
447
if (notifyListHead == NULL) {
448
/* this is the first entry */
449
notifyListHead = newNode;
450
} else {
451
/* go to the last entry; i.e. the first node which's 'next' is NULL.
452
*/
453
currentNode = notifyListHead;
454
while (currentNode->next != NULL) {
455
currentNode = currentNode->next;
456
}
457
currentNode->next = newNode;
458
}
459
460
(*env)->MonitorExit(env, notifyListLock); /* synchronize access to list */
461
}
462
463
/*
464
* Removes the active notifyEncapsulation object used with the given session and
465
* returns it. If there is no notifyEncapsulation active for this session, this
466
* function returns NULL.
467
*/
468
NotifyEncapsulation * removeNotifyEntry(JNIEnv *env, CK_SESSION_HANDLE hSession) {
469
NotifyEncapsulation *notifyEncapsulation;
470
NotifyListNode *currentNode, *previousNode;
471
472
(*env)->MonitorEnter(env, notifyListLock); /* synchronize access to list */
473
474
if (notifyListHead == NULL) {
475
/* this is the first entry */
476
notifyEncapsulation = NULL;
477
} else {
478
/* Find the node with the wanted session handle. Also stop, when we reach
479
* the last entry; i.e. the first node which's 'next' is NULL.
480
*/
481
currentNode = notifyListHead;
482
previousNode = NULL;
483
484
while ((currentNode->hSession != hSession) && (currentNode->next != NULL)) {
485
previousNode = currentNode;
486
currentNode = currentNode->next;
487
}
488
489
if (currentNode->hSession == hSession) {
490
/* We found a entry for the wanted session, now remove it. */
491
if (previousNode == NULL) {
492
/* it's the first node */
493
notifyListHead = currentNode->next;
494
} else {
495
previousNode->next = currentNode->next;
496
}
497
notifyEncapsulation = currentNode->notifyEncapsulation;
498
free(currentNode);
499
} else {
500
/* We did not find a entry for this session */
501
notifyEncapsulation = NULL;
502
}
503
}
504
505
(*env)->MonitorExit(env, notifyListLock); /* synchronize access to list */
506
507
return notifyEncapsulation ;
508
}
509
510
/*
511
512
* Removes the first notifyEncapsulation object. If there is no notifyEncapsulation,
513
* this function returns NULL.
514
*/
515
NotifyEncapsulation * removeFirstNotifyEntry(JNIEnv *env) {
516
NotifyEncapsulation *notifyEncapsulation;
517
NotifyListNode *currentNode;
518
519
(*env)->MonitorEnter(env, notifyListLock); /* synchronize access to list */
520
521
if (notifyListHead == NULL) {
522
/* this is the first entry */
523
notifyEncapsulation = NULL;
524
} else {
525
/* Remove the first entry. */
526
currentNode = notifyListHead;
527
notifyListHead = notifyListHead->next;
528
notifyEncapsulation = currentNode->notifyEncapsulation;
529
free(currentNode);
530
}
531
532
(*env)->MonitorExit(env, notifyListLock); /* synchronize access to list */
533
534
return notifyEncapsulation ;
535
}
536
537
#endif /* NO_CALLBACKS */
538
539
#ifndef NO_CALLBACKS
540
541
/*
542
* The function handling notify callbacks. It casts the pApplication parameter
543
* back to a NotifyEncapsulation structure and retrieves the Notify object and
544
* the application data from it.
545
*
546
* @param hSession The session, this callback is comming from.
547
* @param event The type of event that occurred.
548
* @param pApplication The application data as passed in upon OpenSession. In
549
this wrapper we always pass in a NotifyEncapsulation
550
object, which holds necessary information for delegating
551
the callback to the Java VM.
552
* @return
553
*/
554
CK_RV notifyCallback(
555
CK_SESSION_HANDLE hSession, /* the session's handle */
556
CK_NOTIFICATION event,
557
CK_VOID_PTR pApplication /* passed to C_OpenSession */
558
)
559
{
560
NotifyEncapsulation *notifyEncapsulation;
561
extern JavaVM *jvm;
562
JNIEnv *env;
563
jint returnValue;
564
jlong jSessionHandle;
565
jlong jEvent;
566
jclass ckNotifyClass;
567
jmethodID jmethod;
568
jthrowable pkcs11Exception;
569
jclass pkcs11ExceptionClass;
570
jlong errorCode;
571
CK_RV rv = CKR_OK;
572
int wasAttached = 1;
573
574
if (pApplication == NULL) { return rv ; } /* This should not occur in this wrapper. */
575
576
notifyEncapsulation = (NotifyEncapsulation *) pApplication;
577
578
/* Get the currently running Java VM */
579
if (jvm == NULL) { return rv ; } /* there is no VM running */
580
581
/* Determine, if current thread is already attached */
582
returnValue = (*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION_1_2);
583
if (returnValue == JNI_EDETACHED) {
584
/* thread detached, so attach it */
585
wasAttached = 0;
586
returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL);
587
} else if (returnValue == JNI_EVERSION) {
588
/* this version of JNI is not supported, so just try to attach */
589
/* we assume it was attached to ensure that this thread is not detached
590
* afterwards even though it should not
591
*/
592
wasAttached = 1;
593
returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL);
594
} else {
595
/* attached */
596
wasAttached = 1;
597
}
598
599
jSessionHandle = ckULongToJLong(hSession);
600
jEvent = ckULongToJLong(event);
601
602
ckNotifyClass = (*env)->FindClass(env, CLASS_NOTIFY);
603
if (ckNotifyClass == NULL) { return rv; }
604
jmethod = (*env)->GetMethodID(env, ckNotifyClass, "CK_NOTIFY", "(JJLjava/lang/Object;)V");
605
if (jmethod == NULL) { return rv; }
606
607
(*env)->CallVoidMethod(env, notifyEncapsulation->jNotifyObject, jmethod,
608
jSessionHandle, jEvent, notifyEncapsulation->jApplicationData);
609
610
/* check, if callback threw an exception */
611
pkcs11Exception = (*env)->ExceptionOccurred(env);
612
613
if (pkcs11Exception != NULL) {
614
/* TBD: clear the pending exception with ExceptionClear? */
615
/* The was an exception thrown, now we get the error-code from it */
616
pkcs11ExceptionClass = (*env)->FindClass(env, CLASS_PKCS11EXCEPTION);
617
if (pkcs11ExceptionClass == NULL) { return rv; }
618
619
jmethod = (*env)->GetMethodID(env, pkcs11ExceptionClass, "getErrorCode", "()J");
620
if (jmethod == NULL) { return rv; }
621
622
errorCode = (*env)->CallLongMethod(env, pkcs11Exception, jmethod);
623
rv = jLongToCKULong(errorCode);
624
}
625
626
/* if we attached this thread to the VM just for callback, we detach it now */
627
if (wasAttached) {
628
returnValue = (*jvm)->DetachCurrentThread(jvm);
629
}
630
631
return rv ;
632
}
633
634
#endif /* NO_CALLBACKS */
635
636