1 /*
   2  * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #include <stdlib.h>
  27 #include <string.h>
  28 #include <strings.h>
  29 #include <jni.h>
  30 #include "jni_util.h"
  31 #include "nativeCrypto.h"
  32 #include "nativeFunc.h"
  33 
  34 
  35 extern void throwOutOfMemoryError(JNIEnv *env, const char *msg);
  36 extern jbyte* getBytes(JNIEnv *env, jbyteArray bytes, int offset, int len);
  37 
  38 ///////////////////////////////////////////////////////
  39 // SPECIAL ENTRIES FOR JVM JNI-BYPASSING OPTIMIZATION
  40 ////////////////////////////////////////////////////////
  41 jlong JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeInit(jint mech) {
  42   void *pContext = NULL;
  43 
  44   switch (mech) {
  45   case com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1:
  46     pContext = malloc(sizeof(SHA1_CTX));
  47     if (pContext != NULL) {
  48       (*ftab->sha1Init)((SHA1_CTX *)pContext);
  49     }
  50     break;
  51   case com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5:
  52     pContext = malloc(sizeof(MD5_CTX));
  53     if (pContext != NULL) {
  54       (*ftab->md5Init)((MD5_CTX *)pContext);
  55     }
  56     break;
  57   case com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA256:
  58     pContext = malloc(sizeof(SHA2_CTX));
  59     if (pContext != NULL) {
  60       (*ftab->sha2Init)(SHA256, (SHA2_CTX *)pContext);
  61     }
  62     break;
  63   case com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA384:
  64     pContext = malloc(sizeof(SHA2_CTX));
  65     if (pContext != NULL) {
  66       (*ftab->sha2Init)(SHA384, (SHA2_CTX *)pContext);
  67     }
  68     break;
  69   case com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA512:
  70     pContext = malloc(sizeof(SHA2_CTX));
  71     if (pContext != NULL) {
  72       (*ftab->sha2Init)(SHA512, (SHA2_CTX *)pContext);
  73     }
  74     break;
  75   default:
  76     if (J2UC_DEBUG) printf("ERROR: Unsupported mech %i\n", mech);
  77   }
  78   return (jlong) pContext;
  79 }
  80 
  81 jint JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeUpdate
  82   (jint mech, jlong pContext, int notUsed, unsigned char* in, jint ofs, jint len) {
  83   if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1) {
  84     (*ftab->sha1Update)((SHA1_CTX*)pContext, (unsigned char*)(in+ofs), len);
  85   } else if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5) {
  86     (*ftab->md5Update)((MD5_CTX*)pContext, (unsigned char*)(in+ofs), len);
  87   } else { // SHA-2 family
  88     (*ftab->sha2Update)((SHA2_CTX*)pContext, (unsigned char*)(in+ofs), len);
  89   }
  90   return 0;
  91 }
  92 
  93 // Do digest and free the context immediately
  94 jint JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeDigest
  95   (jint mech, jlong pContext, int notUsed, unsigned char* out, jint ofs, jint digestLen) {
  96 
  97   if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1) {
  98     (*ftab->sha1Final)((unsigned char*)(out + ofs), (SHA1_CTX *)pContext);
  99     free((SHA1_CTX *)pContext);
 100   } else if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5) {
 101     (*ftab->md5Final)((unsigned char*)(out + ofs), (MD5_CTX *)pContext);
 102     free((MD5_CTX *)pContext);
 103   } else { // SHA-2 family
 104     (*ftab->sha2Final)((unsigned char*)(out + ofs), (SHA2_CTX *)pContext);
 105     free((SHA2_CTX *)pContext);
 106   }
 107   return 0;
 108 }
 109 
 110 jlong JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeClone
 111   (jint mech, jlong pContext) {
 112   void *copy = NULL;
 113   size_t len = 0;
 114 
 115   if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1) {
 116     len = sizeof(SHA1_CTX);
 117   } else if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5) {
 118     len = sizeof(MD5_CTX);
 119   } else { // SHA-2 family
 120     len = sizeof(SHA2_CTX);
 121   }
 122   copy = malloc(len);
 123   if (copy != NULL) {
 124     bcopy((void *)pContext, copy, len);
 125   }
 126   return (jlong) copy;
 127 }
 128 
 129 void JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeFree
 130   (jint mech, jlong pContext) {
 131   if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1) {
 132     free((SHA1_CTX*) pContext);
 133   } else if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5) {
 134     free((MD5_CTX*) pContext);
 135   } else { // SHA-2 family
 136     free((SHA2_CTX*) pContext);
 137   }
 138 }
 139 
 140 
 141 /*
 142  * Class:     com_oracle_security_ucrypto_NativeDigestMD
 143  * Method:    nativeInit
 144  * Signature: (I)J
 145  */
 146 JNIEXPORT jlong JNICALL Java_com_oracle_security_ucrypto_NativeDigestMD_nativeInit
 147   (JNIEnv *env, jclass jcls, jint mech) {
 148   jlong result = JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeInit(mech);
 149   if (result == NULL) {
 150      throwOutOfMemoryError(env, NULL);
 151   }
 152   return result;
 153 }
 154 
 155 /*
 156  * Class:     com_oracle_security_ucrypto_NativeDigestMD
 157  * Method:    nativeUpdate
 158  * Signature: (IJ[BII)I
 159  */
 160 JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeDigestMD_nativeUpdate
 161   (JNIEnv *env, jclass jcls, jint mech, jlong pContext, jbyteArray jIn, jint jOfs, jint jLen) {
 162   unsigned char *bufIn;
 163 
 164   bufIn = (unsigned char *) getBytes(env, jIn, jOfs, jLen);
 165   if (!(*env)->ExceptionCheck(env)) {
 166     JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeUpdate(mech, pContext, jLen, bufIn, 0, jLen);
 167     free(bufIn);
 168   }
 169   return 0;
 170 }
 171 
 172 /*
 173  * Class:     com_oracle_security_ucrypto_NativeDigestMD
 174  * Method:    nativeDigest
 175  * Signature: (IJ[BII)I
 176  */
 177 JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeDigestMD_nativeDigest
 178   (JNIEnv *env, jclass jcls, jint mech, jlong pContext, jbyteArray jOut, jint jOutOfs, jint digestLen) {
 179   unsigned char *bufOut;
 180 
 181   bufOut = (unsigned char *) malloc(digestLen);
 182   if (bufOut == NULL) {
 183     throwOutOfMemoryError(env, NULL);
 184     return 0;
 185   }
 186 
 187   JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeDigest(mech, pContext, digestLen, bufOut, 0, digestLen);
 188 
 189   (*env)->SetByteArrayRegion(env, jOut, jOutOfs, digestLen, (jbyte *) bufOut);
 190   free(bufOut);
 191   return 0;
 192 }
 193 
 194 /*
 195  * Class:     com_oracle_security_ucrypto_NativeDigestMD
 196  * Method:    nativeClone
 197  * Signature: (IJ)J
 198  */
 199 JNIEXPORT jlong JNICALL Java_com_oracle_security_ucrypto_NativeDigestMD_nativeClone
 200   (JNIEnv *env, jclass jcls, jint mech, jlong pContext) {
 201   return JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeClone(mech, pContext);
 202 }
 203 
 204 /*
 205  * Class:     com_oracle_security_ucrypto_NativeDigestMD
 206  * Method:    nativeFree
 207  * Signature: (IJ)V
 208  */
 209 JNIEXPORT void JNICALL Java_com_oracle_security_ucrypto_NativeDigestMD_nativeFree
 210   (JNIEnv *env, jclass jcls, jint mech, jlong pContext) {
 211   JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeFree(mech, pContext);
 212 }
 213