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