1/*
2 * Copyright (c) 2003, 2014, 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/*
49 * pkcs11wrapper.c
50 * 18.05.2001
51 *
52 * This module contains the native functions of the Java to PKCS#11 interface
53 * which are platform dependent. This includes loading a dynamic link libary,
54 * retrieving the function list and unloading the dynamic link library.
55 *
56 * @author Karl Scheibelhofer <Karl.Scheibelhofer@iaik.at>
57 */
58
59#include "pkcs11wrapper.h"
60
61#include <stdio.h>
62#include <stdlib.h>
63#include <string.h>
64#include <assert.h>
65
66#include <dlfcn.h>
67
68#include <jni.h>
69
70#include "sun_security_pkcs11_wrapper_PKCS11.h"
71
72/*
73 * Class: sun_security_pkcs11_wrapper_PKCS11
74 * Method: connect
75 * Signature: (Ljava/lang/String;)V
76 */
77JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_connect
78 (JNIEnv *env, jobject obj, jstring jPkcs11ModulePath, jstring jGetFunctionList)
79{
80 void *hModule;
81 char *error;
82 CK_C_GetFunctionList C_GetFunctionList=NULL;
83 CK_RV rv;
84 ModuleData *moduleData;
85 jobject globalPKCS11ImplementationReference;
86 char *systemErrorMessage;
87 char *exceptionMessage;
88 const char *getFunctionListStr;
89
90 const char *libraryNameStr = (*env)->GetStringUTFChars(env, jPkcs11ModulePath, 0);
91 if (libraryNameStr == NULL) {
92 return;
93 }
94 TRACE1("DEBUG: connect to PKCS#11 module: %s ... ", libraryNameStr);
95
96
97 /*
98 * Load the PKCS #11 DLL
99 */
100 dlerror(); /* clear any old error message not fetched */
101#ifdef DEBUG
102 hModule = dlopen(libraryNameStr, RTLD_NOW);
103#else
104 hModule = dlopen(libraryNameStr, RTLD_LAZY);
105#endif /* DEBUG */
106
107 if (hModule == NULL) {
108 systemErrorMessage = dlerror();
109 exceptionMessage = (char *) malloc(sizeof(char) * (strlen(systemErrorMessage) + strlen(libraryNameStr) + 1));
110 if (exceptionMessage == NULL) {
111 throwOutOfMemoryError(env, 0);
112 return;
113 }
114 strcpy(exceptionMessage, systemErrorMessage);
115 strcat(exceptionMessage, libraryNameStr);
116 throwIOException(env, exceptionMessage);
117 (*env)->ReleaseStringUTFChars(env, jPkcs11ModulePath, libraryNameStr);
118 free(exceptionMessage);
119 return;
120 }
121
122 /*
123 * Get function pointer to C_GetFunctionList
124 */
125 dlerror(); /* clear any old error message not fetched */
126 // with the old JAR file jGetFunctionList is null, temporarily check for that
127 if (jGetFunctionList != NULL) {
128 getFunctionListStr = (*env)->GetStringUTFChars(env, jGetFunctionList, 0);
129 if (getFunctionListStr == NULL) {
130 return;
131 }
132 C_GetFunctionList = (CK_C_GetFunctionList) dlsym(hModule, getFunctionListStr);
133 (*env)->ReleaseStringUTFChars(env, jGetFunctionList, getFunctionListStr);
134 }
135 if (C_GetFunctionList == NULL) {
136 throwIOException(env, "ERROR: C_GetFunctionList == NULL");
137 return;
138 } else if ( (systemErrorMessage = dlerror()) != NULL ){
139 throwIOException(env, systemErrorMessage);
140 return;
141 }
142
143 /*
144 * Get function pointers to all PKCS #11 functions
145 */
146 moduleData = (ModuleData *) malloc(sizeof(ModuleData));
147 if (moduleData == NULL) {
148 dlclose(hModule);
149 throwOutOfMemoryError(env, 0);
150 return;
151 }
152 moduleData->hModule = hModule;
153 moduleData->applicationMutexHandler = NULL;
154 rv = (C_GetFunctionList)(&(moduleData->ckFunctionListPtr));
155 globalPKCS11ImplementationReference = (*env)->NewGlobalRef(env, obj);
156 putModuleEntry(env, globalPKCS11ImplementationReference, moduleData);
157
158 (*env)->ReleaseStringUTFChars(env, jPkcs11ModulePath, libraryNameStr);
159 TRACE0("FINISHED\n");
160
161 if(ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; }
162}
163
164/*
165 * Class: sun_security_pkcs11_wrapper_PKCS11
166 * Method: disconnect
167 * Signature: ()V
168 */
169JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_disconnect
170 (JNIEnv *env, jobject obj)
171{
172 ModuleData *moduleData;
173 TRACE0("DEBUG: disconnecting module...");
174 moduleData = removeModuleEntry(env, obj);
175
176 if (moduleData != NULL) {
177 dlclose(moduleData->hModule);
178 }
179
180 free(moduleData);
181 TRACE0("FINISHED\n");
182
183}
184