1 /*
   2  * Copyright (c) 2016, 2018, 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 #include "com_oracle_security_ucrypto_NativeDigestMD.h"
  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 JNIEXPORT jlong JNICALL
  42 JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeInit(jint mech) {
  43   void *pContext = NULL;
  44 
  45   switch (mech) {
  46   case com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1:
  47     pContext = malloc(sizeof(SHA1_CTX));
  48     if (pContext != NULL) {
  49       (*ftab->sha1Init)((SHA1_CTX *)pContext);
  50     }
  51     break;
  52   case com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5:
  53     pContext = malloc(sizeof(MD5_CTX));
  54     if (pContext != NULL) {
  55       (*ftab->md5Init)((MD5_CTX *)pContext);
  56     }
  57     break;
  58   case com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA256:
  59     pContext = malloc(sizeof(SHA2_CTX));
  60     if (pContext != NULL) {
  61       (*ftab->sha2Init)(SHA256, (SHA2_CTX *)pContext);
  62     }
  63     break;
  64   case com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA384:
  65     pContext = malloc(sizeof(SHA2_CTX));
  66     if (pContext != NULL) {
  67       (*ftab->sha2Init)(SHA384, (SHA2_CTX *)pContext);
  68     }
  69     break;
  70   case com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA512:
  71     pContext = malloc(sizeof(SHA2_CTX));
  72     if (pContext != NULL) {
  73       (*ftab->sha2Init)(SHA512, (SHA2_CTX *)pContext);
  74     }
  75     break;
  76   default:
  77     if (J2UC_DEBUG) printf("ERROR: Unsupported mech %i\n", mech);
  78   }
  79   return (jlong) pContext;
  80 }
  81 
  82 JNIEXPORT jint JNICALL
  83 JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeUpdate
  84   (jint mech, jlong pContext, int notUsed, unsigned char* in, jint ofs, jint len) {
  85   if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1) {
  86     (*ftab->sha1Update)((SHA1_CTX*)pContext, (unsigned char*)(in+ofs), len);
  87   } else if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5) {
  88     (*ftab->md5Update)((MD5_CTX*)pContext, (unsigned char*)(in+ofs), len);
  89   } else { // SHA-2 family
  90     (*ftab->sha2Update)((SHA2_CTX*)pContext, (unsigned char*)(in+ofs), len);
  91   }
  92   return 0;
  93 }
  94 
  95 // Do digest and free the context immediately
  96 JNIEXPORT jint JNICALL
  97 JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeDigest
  98   (jint mech, jlong pContext, int notUsed, unsigned char* out, jint ofs, jint digestLen) {
  99 
 100   if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1) {
 101     (*ftab->sha1Final)((unsigned char*)(out + ofs), (SHA1_CTX *)pContext);
 102     free((SHA1_CTX *)pContext);
 103   } else if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5) {
 104     (*ftab->md5Final)((unsigned char*)(out + ofs), (MD5_CTX *)pContext);
 105     free((MD5_CTX *)pContext);
 106   } else { // SHA-2 family
 107     (*ftab->sha2Final)((unsigned char*)(out + ofs), (SHA2_CTX *)pContext);
 108     free((SHA2_CTX *)pContext);
 109   }
 110   return 0;
 111 }
 112 
 113 JNIEXPORT jlong JNICALL
 114 JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeClone
 115   (jint mech, jlong pContext) {
 116   void *copy = NULL;
 117   size_t len = 0;
 118 
 119   if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1) {
 120     len = sizeof(SHA1_CTX);
 121   } else if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5) {
 122     len = sizeof(MD5_CTX);
 123   } else { // SHA-2 family
 124     len = sizeof(SHA2_CTX);
 125   }
 126   copy = malloc(len);
 127   if (copy != NULL) {
 128     bcopy((void *)pContext, copy, len);
 129   }
 130   return (jlong) copy;
 131 }
 132 
 133 JNIEXPORT void JNICALL
 134 JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeFree
 135   (jint mech, jlong pContext) {
 136   if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1) {
 137     free((SHA1_CTX*) pContext);
 138   } else if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5) {
 139     free((MD5_CTX*) pContext);
 140   } else { // SHA-2 family
 141     free((SHA2_CTX*) pContext);
 142   }
 143 }
 144 
 145 
 146 /*
 147  * Class:     com_oracle_security_ucrypto_NativeDigestMD
 148  * Method:    nativeInit
 149  * Signature: (I)J
 150  */
 151 JNIEXPORT jlong JNICALL Java_com_oracle_security_ucrypto_NativeDigestMD_nativeInit
 152   (JNIEnv *env, jclass jcls, jint mech) {
 153   jlong result = JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeInit(mech);
 154   if (result == NULL) {
 155      throwOutOfMemoryError(env, NULL);
 156   }
 157   return result;
 158 }
 159 
 160 /*
 161  * Class:     com_oracle_security_ucrypto_NativeDigestMD
 162  * Method:    nativeUpdate
 163  * Signature: (IJ[BII)I
 164  */
 165 JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeDigestMD_nativeUpdate
 166   (JNIEnv *env, jclass jcls, jint mech, jlong pContext, jbyteArray jIn, jint jOfs, jint jLen) {
 167   unsigned char *bufIn;
 168 
 169   bufIn = (unsigned char *) getBytes(env, jIn, jOfs, jLen);
 170   if (!(*env)->ExceptionCheck(env)) {
 171     JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeUpdate(mech, pContext, jLen, bufIn, 0, jLen);
 172     free(bufIn);
 173   }
 174   return 0;
 175 }
 176 
 177 /*
 178  * Class:     com_oracle_security_ucrypto_NativeDigestMD
 179  * Method:    nativeDigest
 180  * Signature: (IJ[BII)I
 181  */
 182 JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeDigestMD_nativeDigest
 183   (JNIEnv *env, jclass jcls, jint mech, jlong pContext, jbyteArray jOut, jint jOutOfs, jint digestLen) {
 184   unsigned char *bufOut;
 185 
 186   bufOut = (unsigned char *) malloc(digestLen);
 187   if (bufOut == NULL) {
 188     throwOutOfMemoryError(env, NULL);
 189     return 0;
 190   }
 191 
 192   JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeDigest(mech, pContext, digestLen, bufOut, 0, digestLen);
 193 
 194   (*env)->SetByteArrayRegion(env, jOut, jOutOfs, digestLen, (jbyte *) bufOut);
 195   free(bufOut);
 196   return 0;
 197 }
 198 
 199 /*
 200  * Class:     com_oracle_security_ucrypto_NativeDigestMD
 201  * Method:    nativeClone
 202  * Signature: (IJ)J
 203  */
 204 JNIEXPORT jlong JNICALL Java_com_oracle_security_ucrypto_NativeDigestMD_nativeClone
 205   (JNIEnv *env, jclass jcls, jint mech, jlong pContext) {
 206   return JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeClone(mech, pContext);
 207 }
 208 
 209 /*
 210  * Class:     com_oracle_security_ucrypto_NativeDigestMD
 211  * Method:    nativeFree
 212  * Signature: (IJ)V
 213  */
 214 JNIEXPORT void JNICALL Java_com_oracle_security_ucrypto_NativeDigestMD_nativeFree
 215   (JNIEnv *env, jclass jcls, jint mech, jlong pContext) {
 216   JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeFree(mech, pContext);
 217 }
 218