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 #include "jlong.h"
55 
56 #include "sun_security_pkcs11_wrapper_PKCS11.h"
57 
58 #ifdef P11_ENABLE_C_DIGESTINIT
59 /*
60  * Class:     sun_security_pkcs11_wrapper_PKCS11
61  * Method:    C_DigestInit
62  * Signature: (JLsun/security/pkcs11/wrapper/CK_MECHANISM;)V
63  * Parametermapping:                    *PKCS11*
64  * @param   jlong jSessionHandle        CK_SESSION_HANDLE hSession
65  * @param   jobject jMechanism          CK_MECHANISM_PTR pMechanism
66  */
Java_sun_security_pkcs11_wrapper_PKCS11_C_1DigestInit(JNIEnv * env,jobject obj,jlong jSessionHandle,jobject jMechanism)67 JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1DigestInit
68     (JNIEnv *env, jobject obj, jlong jSessionHandle, jobject jMechanism)
69 {
70     CK_SESSION_HANDLE ckSessionHandle;
71     CK_MECHANISM_PTR ckpMechanism = NULL;
72     CK_RV rv;
73 
74     CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
75     if (ckpFunctions == NULL) { return; }
76 
77     ckSessionHandle = jLongToCKULong(jSessionHandle);
78     ckpMechanism = jMechanismToCKMechanismPtr(env, jMechanism);
79     if ((*env)->ExceptionCheck(env)) { return; }
80 
81     rv = (*ckpFunctions->C_DigestInit)(ckSessionHandle, ckpMechanism);
82 
83     freeCKMechanismPtr(ckpMechanism);
84 
85     if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; }
86 }
87 #endif
88 
89 #ifdef P11_ENABLE_C_DIGEST
90 /*
91  * Class:     sun_security_pkcs11_wrapper_PKCS11
92  * Method:    C_Digest
93  * Signature: (J[BII[BII)I
94  * Parametermapping:                    *PKCS11*
95  * @param   jlong jSessionHandle        CK_SESSION_HANDLE hSession
96  * @param   jbyteArray jData            CK_BYTE_PTR pData
97  *                                      CK_ULONG ulDataLen
98  * @return  jbyteArray jDigest          CK_BYTE_PTR pDigest
99  *                                      CK_ULONG_PTR pulDigestLen
100  */
Java_sun_security_pkcs11_wrapper_PKCS11_C_1DigestSingle(JNIEnv * env,jobject obj,jlong jSessionHandle,jobject jMechanism,jbyteArray jIn,jint jInOfs,jint jInLen,jbyteArray jDigest,jint jDigestOfs,jint jDigestLen)101 JNIEXPORT jint JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1DigestSingle
102     (JNIEnv *env, jobject obj, jlong jSessionHandle, jobject jMechanism,
103      jbyteArray jIn, jint jInOfs, jint jInLen, jbyteArray jDigest,
104      jint jDigestOfs, jint jDigestLen)
105 {
106     CK_SESSION_HANDLE ckSessionHandle;
107     CK_RV rv;
108     CK_BYTE BUF[MAX_STACK_BUFFER_LEN];
109     CK_BYTE_PTR bufP = BUF;
110     CK_BYTE DIGESTBUF[MAX_DIGEST_LEN];
111     CK_ULONG ckDigestLength = 0;
112     CK_MECHANISM_PTR ckpMechanism = NULL;
113 
114     CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
115     if (ckpFunctions == NULL) { return 0; }
116 
117     ckSessionHandle = jLongToCKULong(jSessionHandle);
118     ckpMechanism = jMechanismToCKMechanismPtr(env, jMechanism);
119     if ((*env)->ExceptionCheck(env)) { return 0; }
120 
121     rv = (*ckpFunctions->C_DigestInit)(ckSessionHandle, ckpMechanism);
122     if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { goto cleanup; }
123 
124     if (jInLen > MAX_STACK_BUFFER_LEN) {
125         /* always use single part op, even for large data */
126         bufP = (CK_BYTE_PTR) malloc((size_t)jInLen);
127         if (bufP == NULL) {
128             throwOutOfMemoryError(env, 0);
129             goto cleanup;
130         }
131     }
132 
133     (*env)->GetByteArrayRegion(env, jIn, jInOfs, jInLen, (jbyte *)bufP);
134     if ((*env)->ExceptionCheck(env)) {
135         goto cleanup;
136     }
137 
138     ckDigestLength = min(MAX_DIGEST_LEN, jDigestLen);
139 
140     rv = (*ckpFunctions->C_Digest)(ckSessionHandle, bufP, jInLen, DIGESTBUF, &ckDigestLength);
141     if (ckAssertReturnValueOK(env, rv) == CK_ASSERT_OK) {
142         (*env)->SetByteArrayRegion(env, jDigest, jDigestOfs, ckDigestLength, (jbyte *)DIGESTBUF);
143     }
144 cleanup:
145     freeCKMechanismPtr(ckpMechanism);
146     if (bufP != BUF) { free(bufP); }
147 
148     return ckDigestLength;
149 }
150 #endif
151 
152 #ifdef P11_ENABLE_C_DIGESTUPDATE
153 /*
154  * Class:     sun_security_pkcs11_wrapper_PKCS11
155  * Method:    C_DigestUpdate
156  * Signature: (J[B)V
157  * Parametermapping:                    *PKCS11*
158  * @param   jlong jSessionHandle        CK_SESSION_HANDLE hSession
159  * @param   jbyteArray jData            CK_BYTE_PTR pData
160  *                                      CK_ULONG ulDataLen
161  */
Java_sun_security_pkcs11_wrapper_PKCS11_C_1DigestUpdate(JNIEnv * env,jobject obj,jlong jSessionHandle,jlong directIn,jbyteArray jIn,jint jInOfs,jint jInLen)162 JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1DigestUpdate
163     (JNIEnv *env, jobject obj, jlong jSessionHandle, jlong directIn, jbyteArray jIn,
164      jint jInOfs, jint jInLen)
165 {
166     CK_SESSION_HANDLE ckSessionHandle;
167     CK_RV rv;
168     CK_BYTE_PTR bufP;
169     CK_BYTE BUF[MAX_STACK_BUFFER_LEN];
170     jsize bufLen;
171 
172     CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
173     if (ckpFunctions == NULL) { return; }
174 
175     ckSessionHandle = jLongToCKULong(jSessionHandle);
176 
177     if (directIn != 0) {
178         rv = (*ckpFunctions->C_DigestUpdate)(ckSessionHandle, (CK_BYTE_PTR)jlong_to_ptr(directIn), jInLen);
179         ckAssertReturnValueOK(env, rv);
180         return;
181     }
182 
183     if (jInLen <= MAX_STACK_BUFFER_LEN) {
184         bufLen = MAX_STACK_BUFFER_LEN;
185         bufP = BUF;
186     } else {
187         bufLen = min(MAX_HEAP_BUFFER_LEN, jInLen);
188         bufP = (CK_BYTE_PTR) malloc((size_t)bufLen);
189         if (bufP == NULL) {
190             throwOutOfMemoryError(env, 0);
191             return;
192         }
193     }
194 
195     while (jInLen > 0) {
196         jsize chunkLen = min(bufLen, jInLen);
197         (*env)->GetByteArrayRegion(env, jIn, jInOfs, chunkLen, (jbyte *)bufP);
198         if ((*env)->ExceptionCheck(env)) {
199             if (bufP != BUF) { free(bufP); }
200             return;
201         }
202         rv = (*ckpFunctions->C_DigestUpdate)(ckSessionHandle, bufP, chunkLen);
203         if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) {
204             if (bufP != BUF) { free(bufP); }
205             return;
206         }
207         jInOfs += chunkLen;
208         jInLen -= chunkLen;
209     }
210 
211     if (bufP != BUF) {
212         free(bufP);
213     }
214 }
215 #endif
216 
217 #ifdef P11_ENABLE_C_DIGESTKEY
218 /*
219  * Class:     sun_security_pkcs11_wrapper_PKCS11
220  * Method:    C_DigestKey
221  * Signature: (JJ)V
222  * Parametermapping:                    *PKCS11*
223  * @param   jlong jSessionHandle        CK_SESSION_HANDLE hSession
224  * @param   jlong jKeyHandle            CK_OBJECT_HANDLE hKey
225  */
Java_sun_security_pkcs11_wrapper_PKCS11_C_1DigestKey(JNIEnv * env,jobject obj,jlong jSessionHandle,jlong jKeyHandle)226 JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1DigestKey
227     (JNIEnv *env, jobject obj, jlong jSessionHandle, jlong jKeyHandle)
228 {
229     CK_SESSION_HANDLE ckSessionHandle;
230     CK_ULONG ckKeyHandle;
231     CK_RV rv;
232 
233     CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
234     if (ckpFunctions == NULL) { return; }
235 
236     ckSessionHandle = jLongToCKULong(jSessionHandle);
237     ckKeyHandle = jLongToCKULong(jKeyHandle);
238 
239     rv = (*ckpFunctions->C_DigestKey)(ckSessionHandle, ckKeyHandle);
240     if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; }
241 }
242 #endif
243 
244 #ifdef P11_ENABLE_C_DIGESTFINAL
245 /*
246  * Class:     sun_security_pkcs11_wrapper_PKCS11
247  * Method:    C_DigestFinal
248  * Signature: (J[BII)I
249  * Parametermapping:                    *PKCS11*
250  * @param   jlong jSessionHandle        CK_SESSION_HANDLE hSession
251  * @return  jbyteArray jDigest          CK_BYTE_PTR pDigest
252  *                                      CK_ULONG_PTR pulDigestLen
253  */
Java_sun_security_pkcs11_wrapper_PKCS11_C_1DigestFinal(JNIEnv * env,jobject obj,jlong jSessionHandle,jbyteArray jDigest,jint jDigestOfs,jint jDigestLen)254 JNIEXPORT jint JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1DigestFinal
255     (JNIEnv *env, jobject obj, jlong jSessionHandle, jbyteArray jDigest,
256      jint jDigestOfs, jint jDigestLen)
257 {
258     CK_SESSION_HANDLE ckSessionHandle;
259     CK_RV rv;
260     CK_BYTE BUF[MAX_DIGEST_LEN];
261     CK_ULONG ckDigestLength = min(MAX_DIGEST_LEN, jDigestLen);
262 
263     CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
264     if (ckpFunctions == NULL) { return 0; }
265 
266     ckSessionHandle = jLongToCKULong(jSessionHandle);
267 
268     rv = (*ckpFunctions->C_DigestFinal)(ckSessionHandle, BUF, &ckDigestLength);
269     if (ckAssertReturnValueOK(env, rv) == CK_ASSERT_OK) {
270         (*env)->SetByteArrayRegion(env, jDigest, jDigestOfs, ckDigestLength, (jbyte *)BUF);
271     }
272     return ckDigestLength;
273 }
274 #endif
275 
276 #ifdef P11_ENABLE_C_SEEDRANDOM
277 /*
278  * Class:     sun_security_pkcs11_wrapper_PKCS11
279  * Method:    C_SeedRandom
280  * Signature: (J[B)V
281  * Parametermapping:                    *PKCS11*
282  * @param   jlong jSessionHandle        CK_SESSION_HANDLE hSession
283  * @param   jbyteArray jSeed            CK_BYTE_PTR pSeed
284  *                                      CK_ULONG ulSeedLen
285  */
Java_sun_security_pkcs11_wrapper_PKCS11_C_1SeedRandom(JNIEnv * env,jobject obj,jlong jSessionHandle,jbyteArray jSeed)286 JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1SeedRandom
287     (JNIEnv *env, jobject obj, jlong jSessionHandle, jbyteArray jSeed)
288 {
289     CK_SESSION_HANDLE ckSessionHandle;
290     CK_BYTE_PTR ckpSeed = NULL_PTR;
291     CK_ULONG ckSeedLength;
292     CK_RV rv;
293 
294     CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
295     if (ckpFunctions == NULL) { return; }
296 
297     ckSessionHandle = jLongToCKULong(jSessionHandle);
298     jByteArrayToCKByteArray(env, jSeed, &ckpSeed, &ckSeedLength);
299     if ((*env)->ExceptionCheck(env)) { return; }
300 
301     rv = (*ckpFunctions->C_SeedRandom)(ckSessionHandle, ckpSeed, ckSeedLength);
302 
303     free(ckpSeed);
304 
305     if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; }
306 }
307 #endif
308 
309 #ifdef P11_ENABLE_C_GENERATERANDOM
310 /*
311  * Class:     sun_security_pkcs11_wrapper_PKCS11
312  * Method:    C_GenerateRandom
313  * Signature: (J[B)V
314  * Parametermapping:                    *PKCS11*
315  * @param   jlong jSessionHandle        CK_SESSION_HANDLE hSession
316  * @param   jbyteArray jRandomData      CK_BYTE_PTR pRandomData
317  *                                      CK_ULONG ulRandomDataLen
318  */
Java_sun_security_pkcs11_wrapper_PKCS11_C_1GenerateRandom(JNIEnv * env,jobject obj,jlong jSessionHandle,jbyteArray jRandomData)319 JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1GenerateRandom
320     (JNIEnv *env, jobject obj, jlong jSessionHandle, jbyteArray jRandomData)
321 {
322     CK_SESSION_HANDLE ckSessionHandle;
323     jbyte *jRandomBuffer;
324     jlong jRandomBufferLength;
325     CK_RV rv;
326 
327     CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
328     if (ckpFunctions == NULL) { return; }
329 
330     ckSessionHandle = jLongToCKULong(jSessionHandle);
331 
332     jRandomBufferLength = (*env)->GetArrayLength(env, jRandomData);
333     jRandomBuffer = (*env)->GetByteArrayElements(env, jRandomData, NULL);
334     if (jRandomBuffer == NULL) { return; }
335 
336     rv = (*ckpFunctions->C_GenerateRandom)(ckSessionHandle,
337                                          (CK_BYTE_PTR) jRandomBuffer,
338                                          jLongToCKULong(jRandomBufferLength));
339 
340     /* copy back generated bytes */
341     (*env)->ReleaseByteArrayElements(env, jRandomData, jRandomBuffer, 0);
342 
343     if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; }
344 }
345 #endif
346