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
35extern void throwOutOfMemoryError(JNIEnv *env, const char *msg);
36extern jbyte* getBytes(JNIEnv *env, jbyteArray bytes, int offset, int len);
37
38///////////////////////////////////////////////////////
39// SPECIAL ENTRIES FOR JVM JNI-BYPASSING OPTIMIZATION
40////////////////////////////////////////////////////////
41jlong 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
81jint 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
94jint 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
110jlong 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
129void 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 */
146JNIEXPORT 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 */
160JNIEXPORT 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 */
177JNIEXPORT 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 */
199JNIEXPORT 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 */
209JNIEXPORT 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
214