1/*
2 * Copyright (c) 2003, 2012, 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_SIGNINIT
59/*
60 * Class:     sun_security_pkcs11_wrapper_PKCS11
61 * Method:    C_SignInit
62 * Signature: (JLsun/security/pkcs11/wrapper/CK_MECHANISM;J)V
63 * Parametermapping:                    *PKCS11*
64 * @param   jlong jSessionHandle        CK_SESSION_HANDLE hSession
65 * @param   jobject jMechanism          CK_MECHANISM_PTR pMechanism
66 * @return  jlong jKeyHandle            CK_OBJECT_HANDLE hKey
67 */
68JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1SignInit
69    (JNIEnv *env, jobject obj, jlong jSessionHandle, jobject jMechanism, jlong jKeyHandle)
70{
71    CK_SESSION_HANDLE ckSessionHandle;
72    CK_MECHANISM ckMechanism;
73    CK_OBJECT_HANDLE ckKeyHandle;
74    CK_RV rv;
75
76    CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
77    if (ckpFunctions == NULL) { return; }
78
79    ckSessionHandle = jLongToCKULong(jSessionHandle);
80    jMechanismToCKMechanism(env, jMechanism, &ckMechanism);
81    if ((*env)->ExceptionCheck(env)) { return; }
82    ckKeyHandle = jLongToCKULong(jKeyHandle);
83
84    rv = (*ckpFunctions->C_SignInit)(ckSessionHandle, &ckMechanism, ckKeyHandle);
85
86    if (ckMechanism.pParameter != NULL_PTR) {
87        free(ckMechanism.pParameter);
88    }
89
90    if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; }
91}
92#endif
93
94#ifdef P11_ENABLE_C_SIGN
95/*
96 * Class:     sun_security_pkcs11_wrapper_PKCS11
97 * Method:    C_Sign
98 * Signature: (J[B)[B
99 * Parametermapping:                    *PKCS11*
100 * @param   jlong jSessionHandle        CK_SESSION_HANDLE hSession
101 * @param   jbyteArray jData            CK_BYTE_PTR pData
102 *                                      CK_ULONG ulDataLen
103 * @return  jbyteArray jSignature       CK_BYTE_PTR pSignature
104 *                                      CK_ULONG_PTR pulSignatureLen
105 */
106JNIEXPORT jbyteArray JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1Sign
107    (JNIEnv *env, jobject obj, jlong jSessionHandle, jbyteArray jData)
108{
109    CK_SESSION_HANDLE ckSessionHandle;
110    CK_BYTE_PTR ckpData = NULL_PTR;
111    CK_BYTE_PTR ckpSignature;
112    CK_ULONG ckDataLength;
113    CK_ULONG ckSignatureLength = 0;
114    jbyteArray jSignature = NULL;
115    CK_RV rv;
116
117    CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
118    if (ckpFunctions == NULL) { return NULL; }
119
120    ckSessionHandle = jLongToCKULong(jSessionHandle);
121    jByteArrayToCKByteArray(env, jData, &ckpData, &ckDataLength);
122    if ((*env)->ExceptionCheck(env)) { return NULL; }
123
124    /* START standard code */
125
126    /* first determine the length of the signature */
127    rv = (*ckpFunctions->C_Sign)(ckSessionHandle, ckpData, ckDataLength, NULL_PTR, &ckSignatureLength);
128    if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) {
129        free(ckpData);
130        return NULL;
131    }
132
133    ckpSignature = (CK_BYTE_PTR) malloc(ckSignatureLength * sizeof(CK_BYTE));
134    if (ckpSignature == NULL) {
135        free(ckpData);
136        throwOutOfMemoryError(env, 0);
137        return NULL;
138    }
139
140    /* now get the signature */
141    rv = (*ckpFunctions->C_Sign)(ckSessionHandle, ckpData, ckDataLength, ckpSignature, &ckSignatureLength);
142 /* END standard code */
143
144
145    /* START workaround code for operation abort bug in pkcs#11 of Datakey and iButton */
146/*
147    ckpSignature = (CK_BYTE_PTR) malloc(256 * sizeof(CK_BYTE));
148    if (ckpSignature == NULL) {
149        free(ckpData);
150        throwOutOfMemoryError(env, 0);
151        return NULL;
152    }
153    rv = (*ckpFunctions->C_Sign)(ckSessionHandle, ckpData, ckDataLength, ckpSignature, &ckSignatureLength);
154
155    if (rv == CKR_BUFFER_TOO_SMALL) {
156        free(ckpSignature);
157        ckpSignature = (CK_BYTE_PTR) malloc(ckSignatureLength * sizeof(CK_BYTE));
158        if (ckpSignature == NULL) {
159            free(ckpData);
160            throwOutOfMemoryError(env, 0);
161            return NULL;
162        }
163        rv = (*ckpFunctions->C_Sign)(ckSessionHandle, ckpData, ckDataLength, ckpSignature, &ckSignatureLength);
164    }
165 */
166    /* END workaround code */
167    if (ckAssertReturnValueOK(env, rv) == CK_ASSERT_OK) {
168        jSignature = ckByteArrayToJByteArray(env, ckpSignature, ckSignatureLength);
169    }
170    free(ckpData);
171    free(ckpSignature);
172
173    return jSignature ;
174}
175#endif
176
177#ifdef P11_ENABLE_C_SIGNUPDATE
178/*
179 * Class:     sun_security_pkcs11_wrapper_PKCS11
180 * Method:    C_SignUpdate
181 * Signature: (J[BII)V
182 * Parametermapping:                    *PKCS11*
183 * @param   jlong jSessionHandle        CK_SESSION_HANDLE hSession
184 * @param   jbyteArray jPart            CK_BYTE_PTR pPart
185 *                                      CK_ULONG ulPartLen
186 */
187JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1SignUpdate
188  (JNIEnv *env, jobject obj, jlong jSessionHandle, jlong directIn, jbyteArray jIn, jint jInOfs, jint jInLen)
189{
190    CK_SESSION_HANDLE ckSessionHandle;
191    CK_RV rv;
192    CK_BYTE_PTR bufP;
193    CK_BYTE BUF[MAX_STACK_BUFFER_LEN];
194    jsize bufLen;
195
196    CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
197    if (ckpFunctions == NULL) { return; }
198
199    ckSessionHandle = jLongToCKULong(jSessionHandle);
200
201    if (directIn != 0) {
202        rv = (*ckpFunctions->C_SignUpdate)(ckSessionHandle, (CK_BYTE_PTR) jlong_to_ptr(directIn), jInLen);
203        ckAssertReturnValueOK(env, rv);
204        return;
205    }
206
207    if (jInLen <= MAX_STACK_BUFFER_LEN) {
208        bufLen = MAX_STACK_BUFFER_LEN;
209        bufP = BUF;
210    } else {
211        bufLen = min(MAX_HEAP_BUFFER_LEN, jInLen);
212        bufP = (CK_BYTE_PTR) malloc((size_t)bufLen);
213        if (bufP == NULL) {
214            throwOutOfMemoryError(env, 0);
215            return;
216        }
217    }
218
219    while (jInLen > 0) {
220        jsize chunkLen = min(bufLen, jInLen);
221        (*env)->GetByteArrayRegion(env, jIn, jInOfs, chunkLen, (jbyte *)bufP);
222        if ((*env)->ExceptionCheck(env)) {
223            if (bufP != BUF) { free(bufP); }
224            return;
225        }
226        rv = (*ckpFunctions->C_SignUpdate)(ckSessionHandle, bufP, chunkLen);
227        if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) {
228            if (bufP != BUF) {
229                free(bufP);
230            }
231            return;
232        }
233        jInOfs += chunkLen;
234        jInLen -= chunkLen;
235    }
236
237    if (bufP != BUF) { free(bufP); }
238}
239#endif
240
241#ifdef P11_ENABLE_C_SIGNFINAL
242/*
243 * Class:     sun_security_pkcs11_wrapper_PKCS11
244 * Method:    C_SignFinal
245 * Signature: (J)[B
246 * Parametermapping:                    *PKCS11*
247 * @param   jlong jSessionHandle        CK_SESSION_HANDLE hSession
248 * @return  jbyteArray jSignature       CK_BYTE_PTR pSignature
249 *                                      CK_ULONG_PTR pulSignatureLen
250 */
251JNIEXPORT jbyteArray JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1SignFinal
252    (JNIEnv *env, jobject obj, jlong jSessionHandle, jint jExpectedLength)
253{
254    CK_SESSION_HANDLE ckSessionHandle;
255    jbyteArray jSignature = NULL;
256    CK_RV rv;
257    CK_BYTE BUF[MAX_STACK_BUFFER_LEN];
258    CK_BYTE_PTR bufP = BUF;
259    CK_ULONG ckSignatureLength = MAX_STACK_BUFFER_LEN;
260
261    CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
262    if (ckpFunctions == NULL) { return NULL; }
263
264    ckSessionHandle = jLongToCKULong(jSessionHandle);
265
266    if ((jExpectedLength > 0) && ((CK_ULONG)jExpectedLength < ckSignatureLength)) {
267        ckSignatureLength = jExpectedLength;
268    }
269
270    rv = (*ckpFunctions->C_SignFinal)(ckSessionHandle, bufP, &ckSignatureLength);
271    if (rv == CKR_BUFFER_TOO_SMALL) {
272        bufP = (CK_BYTE_PTR) malloc(ckSignatureLength);
273        if (bufP == NULL) {
274            throwOutOfMemoryError(env, 0);
275            return NULL;
276        }
277        rv = (*ckpFunctions->C_SignFinal)(ckSessionHandle, bufP, &ckSignatureLength);
278    }
279    if (ckAssertReturnValueOK(env, rv) == CK_ASSERT_OK) {
280        jSignature = ckByteArrayToJByteArray(env, bufP, ckSignatureLength);
281    }
282
283    if (bufP != BUF) { free(bufP); }
284
285    return jSignature;
286}
287#endif
288
289#ifdef P11_ENABLE_C_SIGNRECOVERINIT
290/*
291 * Class:     sun_security_pkcs11_wrapper_PKCS11
292 * Method:    C_SignRecoverInit
293 * Signature: (JLsun/security/pkcs11/wrapper/CK_MECHANISM;J)V
294 * Parametermapping:                    *PKCS11*
295 * @param   jlong jSessionHandle        CK_SESSION_HANDLE hSession
296 * @param   jobject jMechanism          CK_MECHANISM_PTR pMechanism
297 * @return  jlong jKeyHandle            CK_OBJECT_HANDLE hKey
298 */
299JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1SignRecoverInit
300    (JNIEnv *env, jobject obj, jlong jSessionHandle, jobject jMechanism, jlong jKeyHandle)
301{
302    CK_SESSION_HANDLE ckSessionHandle;
303    CK_MECHANISM ckMechanism;
304    CK_OBJECT_HANDLE ckKeyHandle;
305    CK_RV rv;
306
307    CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
308    if (ckpFunctions == NULL) { return; }
309
310    ckSessionHandle = jLongToCKULong(jSessionHandle);
311    jMechanismToCKMechanism(env, jMechanism, &ckMechanism);
312    if ((*env)->ExceptionCheck(env)) { return; }
313
314    ckKeyHandle = jLongToCKULong(jKeyHandle);
315
316    rv = (*ckpFunctions->C_SignRecoverInit)(ckSessionHandle, &ckMechanism, ckKeyHandle);
317
318    if (ckMechanism.pParameter != NULL_PTR) {
319        free(ckMechanism.pParameter);
320    }
321
322    if(ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; }
323}
324#endif
325
326#ifdef P11_ENABLE_C_SIGNRECOVER
327/*
328 * Class:     sun_security_pkcs11_wrapper_PKCS11
329 * Method:    C_SignRecover
330 * Signature: (J[BII[BII)I
331 * Parametermapping:                    *PKCS11*
332 * @param   jlong jSessionHandle        CK_SESSION_HANDLE hSession
333 * @param   jbyteArray jData            CK_BYTE_PTR pData
334 *                                      CK_ULONG ulDataLen
335 * @return  jbyteArray jSignature       CK_BYTE_PTR pSignature
336 *                                      CK_ULONG_PTR pulSignatureLen
337 */
338JNIEXPORT jint JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1SignRecover
339  (JNIEnv *env, jobject obj, jlong jSessionHandle, jbyteArray jIn, jint jInOfs, jint jInLen, jbyteArray jOut, jint jOutOfs, jint jOutLen)
340{
341    CK_SESSION_HANDLE ckSessionHandle;
342    CK_RV rv;
343    CK_BYTE INBUF[MAX_STACK_BUFFER_LEN];
344    CK_BYTE OUTBUF[MAX_STACK_BUFFER_LEN];
345    CK_BYTE_PTR inBufP;
346    CK_BYTE_PTR outBufP = OUTBUF;
347    CK_ULONG ckSignatureLength = MAX_STACK_BUFFER_LEN;
348
349    CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
350    if (ckpFunctions == NULL) { return 0; }
351
352    ckSessionHandle = jLongToCKULong(jSessionHandle);
353
354    if (jInLen <= MAX_STACK_BUFFER_LEN) {
355        inBufP = INBUF;
356    } else {
357        inBufP = (CK_BYTE_PTR) malloc((size_t)jInLen);
358        if (inBufP == NULL) {
359            throwOutOfMemoryError(env, 0);
360            return 0;
361        }
362    }
363
364    (*env)->GetByteArrayRegion(env, jIn, jInOfs, jInLen, (jbyte *)inBufP);
365    if ((*env)->ExceptionCheck(env)) {
366        if (inBufP != INBUF) { free(inBufP); }
367        return 0;
368    }
369    rv = (*ckpFunctions->C_SignRecover)(ckSessionHandle, inBufP, jInLen, outBufP, &ckSignatureLength);
370    /* re-alloc larger buffer if it fits into our Java buffer */
371    if ((rv == CKR_BUFFER_TOO_SMALL) && (ckSignatureLength <= jIntToCKULong(jOutLen))) {
372        outBufP = (CK_BYTE_PTR) malloc(ckSignatureLength);
373        if (outBufP == NULL) {
374            if (inBufP != INBUF) {
375                free(inBufP);
376            }
377            throwOutOfMemoryError(env, 0);
378            return 0;
379        }
380        rv = (*ckpFunctions->C_SignRecover)(ckSessionHandle, inBufP, jInLen, outBufP, &ckSignatureLength);
381    }
382    if (ckAssertReturnValueOK(env, rv) == CK_ASSERT_OK) {
383        (*env)->SetByteArrayRegion(env, jOut, jOutOfs, ckSignatureLength, (jbyte *)outBufP);
384    }
385
386    if (inBufP != INBUF) { free(inBufP); }
387    if (outBufP != OUTBUF) { free(outBufP); }
388
389    return ckSignatureLength;
390}
391#endif
392
393#ifdef P11_ENABLE_C_VERIFYINIT
394/*
395 * Class:     sun_security_pkcs11_wrapper_PKCS11
396 * Method:    C_VerifyInit
397 * Signature: (JLsun/security/pkcs11/wrapper/CK_MECHANISM;J)V
398 * Parametermapping:                    *PKCS11*
399 * @param   jlong jSessionHandle        CK_SESSION_HANDLE hSession
400 * @param   jobject jMechanism          CK_MECHANISM_PTR pMechanism
401 * @return  jlong jKeyHandle            CK_OBJECT_HANDLE hKey
402 */
403JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1VerifyInit
404    (JNIEnv *env, jobject obj, jlong jSessionHandle, jobject jMechanism, jlong jKeyHandle)
405{
406    CK_SESSION_HANDLE ckSessionHandle;
407    CK_MECHANISM ckMechanism;
408    CK_OBJECT_HANDLE ckKeyHandle;
409    CK_RV rv;
410
411    CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
412    if (ckpFunctions == NULL) { return; }
413
414    ckSessionHandle = jLongToCKULong(jSessionHandle);
415    jMechanismToCKMechanism(env, jMechanism, &ckMechanism);
416    if ((*env)->ExceptionCheck(env)) { return; }
417
418    ckKeyHandle = jLongToCKULong(jKeyHandle);
419
420    rv = (*ckpFunctions->C_VerifyInit)(ckSessionHandle, &ckMechanism, ckKeyHandle);
421
422    if(ckMechanism.pParameter != NULL_PTR) {
423        free(ckMechanism.pParameter);
424    }
425
426    if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; }
427}
428#endif
429
430#ifdef P11_ENABLE_C_VERIFY
431/*
432 * Class:     sun_security_pkcs11_wrapper_PKCS11
433 * Method:    C_Verify
434 * Signature: (J[B[B)V
435 * Parametermapping:                    *PKCS11*
436 * @param   jlong jSessionHandle        CK_SESSION_HANDLE hSession
437 * @param   jbyteArray jData            CK_BYTE_PTR pData
438 *                                      CK_ULONG ulDataLen
439 * @param   jbyteArray jSignature       CK_BYTE_PTR pSignature
440 *                                      CK_ULONG_PTR pulSignatureLen
441 */
442JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1Verify
443    (JNIEnv *env, jobject obj, jlong jSessionHandle, jbyteArray jData, jbyteArray jSignature)
444{
445    CK_SESSION_HANDLE ckSessionHandle;
446    CK_BYTE_PTR ckpData = NULL_PTR;
447    CK_BYTE_PTR ckpSignature = NULL_PTR;
448    CK_ULONG ckDataLength;
449    CK_ULONG ckSignatureLength;
450    CK_RV rv;
451
452    CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
453    if (ckpFunctions == NULL) { return; }
454
455    ckSessionHandle = jLongToCKULong(jSessionHandle);
456    jByteArrayToCKByteArray(env, jData, &ckpData, &ckDataLength);
457    if ((*env)->ExceptionCheck(env)) { return; }
458
459    jByteArrayToCKByteArray(env, jSignature, &ckpSignature, &ckSignatureLength);
460    if ((*env)->ExceptionCheck(env)) {
461        free(ckpData);
462        return;
463    }
464
465    /* verify the signature */
466    rv = (*ckpFunctions->C_Verify)(ckSessionHandle, ckpData, ckDataLength, ckpSignature, ckSignatureLength);
467
468    free(ckpData);
469    free(ckpSignature);
470
471    if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; }
472}
473#endif
474
475#ifdef P11_ENABLE_C_VERIFYUPDATE
476/*
477 * Class:     sun_security_pkcs11_wrapper_PKCS11
478 * Method:    C_VerifyUpdate
479 * Signature: (J[BII)V
480 * Parametermapping:                    *PKCS11*
481 * @param   jlong jSessionHandle        CK_SESSION_HANDLE hSession
482 * @param   jbyteArray jPart            CK_BYTE_PTR pPart
483 *                                      CK_ULONG ulPartLen
484 */
485JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1VerifyUpdate
486  (JNIEnv *env, jobject obj, jlong jSessionHandle, jlong directIn, jbyteArray jIn, jint jInOfs, jint jInLen)
487{
488    CK_SESSION_HANDLE ckSessionHandle;
489    CK_RV rv;
490    CK_BYTE_PTR bufP;
491    CK_BYTE BUF[MAX_STACK_BUFFER_LEN];
492    jsize bufLen;
493
494    CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
495    if (ckpFunctions == NULL) { return; }
496
497    ckSessionHandle = jLongToCKULong(jSessionHandle);
498
499    if (directIn != 0) {
500        rv = (*ckpFunctions->C_VerifyUpdate)(ckSessionHandle, (CK_BYTE_PTR)jlong_to_ptr(directIn), jInLen);
501        ckAssertReturnValueOK(env, rv);
502        return;
503    }
504
505    if (jInLen <= MAX_STACK_BUFFER_LEN) {
506        bufLen = MAX_STACK_BUFFER_LEN;
507        bufP = BUF;
508    } else {
509        bufLen = min(MAX_HEAP_BUFFER_LEN, jInLen);
510        bufP = (CK_BYTE_PTR) malloc((size_t)bufLen);
511        if (bufP == NULL) {
512            throwOutOfMemoryError(env, 0);
513            return;
514        }
515    }
516
517    while (jInLen > 0) {
518        jsize chunkLen = min(bufLen, jInLen);
519        (*env)->GetByteArrayRegion(env, jIn, jInOfs, chunkLen, (jbyte *)bufP);
520        if ((*env)->ExceptionCheck(env)) {
521            if (bufP != BUF) { free(bufP); }
522            return;
523        }
524
525        rv = (*ckpFunctions->C_VerifyUpdate)(ckSessionHandle, bufP, chunkLen);
526        if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) {
527            if (bufP != BUF) { free(bufP); }
528            return;
529        }
530        jInOfs += chunkLen;
531        jInLen -= chunkLen;
532    }
533
534    if (bufP != BUF) { free(bufP); }
535}
536#endif
537
538#ifdef P11_ENABLE_C_VERIFYFINAL
539/*
540 * Class:     sun_security_pkcs11_wrapper_PKCS11
541 * Method:    C_VerifyFinal
542 * Signature: (J[B)V
543 * Parametermapping:                    *PKCS11*
544 * @param   jlong jSessionHandle        CK_SESSION_HANDLE hSession
545 * @param   jbyteArray jSignature       CK_BYTE_PTR pSignature
546 *                                      CK_ULONG ulSignatureLen
547 */
548JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1VerifyFinal
549    (JNIEnv *env, jobject obj, jlong jSessionHandle, jbyteArray jSignature)
550{
551    CK_SESSION_HANDLE ckSessionHandle;
552    CK_BYTE_PTR ckpSignature = NULL_PTR;
553    CK_ULONG ckSignatureLength;
554    CK_RV rv;
555
556    CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
557    if (ckpFunctions == NULL) { return; }
558
559    ckSessionHandle = jLongToCKULong(jSessionHandle);
560    jByteArrayToCKByteArray(env, jSignature, &ckpSignature, &ckSignatureLength);
561    if ((*env)->ExceptionCheck(env)) { return; }
562
563    /* verify the signature */
564    rv = (*ckpFunctions->C_VerifyFinal)(ckSessionHandle, ckpSignature, ckSignatureLength);
565
566    free(ckpSignature);
567
568    if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; }
569}
570#endif
571
572#ifdef P11_ENABLE_C_VERIFYRECOVERINIT
573/*
574 * Class:     sun_security_pkcs11_wrapper_PKCS11
575 * Method:    C_VerifyRecoverInit
576 * Signature: (JLsun/security/pkcs11/wrapper/CK_MECHANISM;J)V
577 * Parametermapping:                    *PKCS11*
578 * @param   jlong jSessionHandle        CK_SESSION_HANDLE hSession
579 * @param   jobject jMechanism          CK_MECHANISM_PTR pMechanism
580 * @return  jlong jKeyHandle            CK_OBJECT_HANDLE hKey
581 */
582JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1VerifyRecoverInit
583    (JNIEnv *env, jobject obj, jlong jSessionHandle, jobject jMechanism, jlong jKeyHandle)
584{
585    CK_SESSION_HANDLE ckSessionHandle;
586    CK_MECHANISM ckMechanism;
587    CK_OBJECT_HANDLE ckKeyHandle;
588    CK_RV rv;
589
590    CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
591    if (ckpFunctions == NULL) { return; }
592
593    ckSessionHandle = jLongToCKULong(jSessionHandle);
594    jMechanismToCKMechanism(env, jMechanism, &ckMechanism);
595    if ((*env)->ExceptionCheck(env)) { return; }
596
597    ckKeyHandle = jLongToCKULong(jKeyHandle);
598
599    rv = (*ckpFunctions->C_VerifyRecoverInit)(ckSessionHandle, &ckMechanism, ckKeyHandle);
600
601    if (ckMechanism.pParameter != NULL_PTR) {
602        free(ckMechanism.pParameter);
603    }
604
605    if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; }
606}
607#endif
608
609#ifdef P11_ENABLE_C_VERIFYRECOVER
610/*
611 * Class:     sun_security_pkcs11_wrapper_PKCS11
612 * Method:    C_VerifyRecover
613 * Signature: (J[BII[BII)I
614 * Parametermapping:                    *PKCS11*
615 * @param   jlong jSessionHandle        CK_SESSION_HANDLE hSession
616 * @param   jbyteArray jSignature       CK_BYTE_PTR pSignature
617 *                                      CK_ULONG ulSignatureLen
618 * @return  jbyteArray jData            CK_BYTE_PTR pData
619 *                                      CK_ULONG_PTR pulDataLen
620 */
621JNIEXPORT jint JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1VerifyRecover
622  (JNIEnv *env, jobject obj, jlong jSessionHandle, jbyteArray jIn, jint jInOfs, jint jInLen, jbyteArray jOut, jint jOutOfs, jint jOutLen)
623{
624    CK_SESSION_HANDLE ckSessionHandle;
625    CK_RV rv;
626    CK_BYTE INBUF[MAX_STACK_BUFFER_LEN];
627    CK_BYTE OUTBUF[MAX_STACK_BUFFER_LEN];
628    CK_BYTE_PTR inBufP;
629    CK_BYTE_PTR outBufP = OUTBUF;
630    CK_ULONG ckDataLength = MAX_STACK_BUFFER_LEN;
631
632    CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
633    if (ckpFunctions == NULL) { return 0; }
634
635    ckSessionHandle = jLongToCKULong(jSessionHandle);
636
637    if (jInLen <= MAX_STACK_BUFFER_LEN) {
638        inBufP = INBUF;
639    } else {
640        inBufP = (CK_BYTE_PTR) malloc((size_t)jInLen);
641        if (inBufP == NULL) {
642            throwOutOfMemoryError(env, 0);
643            return 0;
644        }
645    }
646
647    (*env)->GetByteArrayRegion(env, jIn, jInOfs, jInLen, (jbyte *)inBufP);
648    if ((*env)->ExceptionCheck(env)) {
649        if (inBufP != INBUF) { free(inBufP); }
650        return 0;
651    }
652
653    rv = (*ckpFunctions->C_VerifyRecover)(ckSessionHandle, inBufP, jInLen, outBufP, &ckDataLength);
654
655    /* re-alloc larger buffer if it fits into our Java buffer */
656    if ((rv == CKR_BUFFER_TOO_SMALL) && (ckDataLength <= jIntToCKULong(jOutLen))) {
657        outBufP = (CK_BYTE_PTR) malloc(ckDataLength);
658        if (outBufP == NULL) {
659            if (inBufP != INBUF) { free(inBufP); }
660            throwOutOfMemoryError(env, 0);
661            return 0;
662        }
663        rv = (*ckpFunctions->C_VerifyRecover)(ckSessionHandle, inBufP, jInLen, outBufP, &ckDataLength);
664    }
665    if (ckAssertReturnValueOK(env, rv) == CK_ASSERT_OK) {
666        (*env)->SetByteArrayRegion(env, jOut, jOutOfs, ckDataLength, (jbyte *)outBufP);
667    }
668
669    if (inBufP != INBUF) { free(inBufP); }
670    if (outBufP != OUTBUF) { free(outBufP); }
671
672    return ckDataLength;
673}
674#endif
675