Home | History | Annotate | Download | only in jni
      1 /*
      2  * Copyright (C) 2006 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "jni.h"
     18 #include <JNIHelp.h>
     19 #include <stdlib.h>
     20 #include <stdint.h>
     21 
     22 #include <openssl/md5.h>
     23 
     24 namespace android
     25 {
     26 
     27 struct fields_t {
     28     jfieldID    context;
     29 };
     30 static fields_t fields;
     31 
     32 static void native_init(JNIEnv *env, jobject clazz)
     33 {
     34     MD5_CTX* context = (MD5_CTX *)malloc(sizeof(MD5_CTX));
     35     MD5_Init(context);
     36 
     37     env->SetIntField(clazz, fields.context, (int)context);
     38 }
     39 
     40 static void native_reset(JNIEnv *env, jobject clazz)
     41 {
     42     MD5_CTX *context = (MD5_CTX *)env->GetIntField(clazz, fields.context);
     43     if (context != NULL) {
     44         free(context);
     45         env->SetIntField(clazz, fields.context, 0 );
     46     }
     47 }
     48 
     49 static void native_update(JNIEnv *env, jobject clazz, jbyteArray dataArray)
     50 {
     51     jbyte * data;
     52     jsize dataSize;
     53     MD5_CTX *context = (MD5_CTX *)env->GetIntField(clazz, fields.context);
     54 
     55     if (context == NULL) {
     56         native_init(env, clazz);
     57         context = (MD5_CTX *)env->GetIntField(clazz, fields.context);
     58     }
     59 
     60     data = env->GetByteArrayElements(dataArray, NULL);
     61     if (data == NULL) {
     62         LOGE("Unable to get byte array elements");
     63         jniThrowException(env, "java/lang/IllegalArgumentException",
     64                           "Invalid data array when calling MessageDigest.update()");
     65         return;
     66     }
     67     dataSize = env->GetArrayLength(dataArray);
     68 
     69     MD5_Update(context, data, dataSize);
     70 
     71     env->ReleaseByteArrayElements(dataArray, data, 0);
     72 }
     73 
     74 static jbyteArray native_digest(JNIEnv *env, jobject clazz)
     75 {
     76     jbyteArray array;
     77     jbyte md[MD5_DIGEST_LENGTH];
     78     MD5_CTX *context = (MD5_CTX *)env->GetIntField(clazz, fields.context);
     79 
     80     MD5_Final((uint8_t*)md, context);
     81 
     82     array = env->NewByteArray(MD5_DIGEST_LENGTH);
     83     LOG_ASSERT(array, "Native could not create new byte[]");
     84 
     85     env->SetByteArrayRegion(array, 0, MD5_DIGEST_LENGTH, md);
     86 
     87     native_reset(env, clazz);
     88 
     89     return array;
     90 }
     91 
     92 
     93 /*
     94  * JNI registration.
     95  */
     96 
     97 static JNINativeMethod gMethods[] =
     98 {
     99      /* name, signature, funcPtr */
    100     {"init", "()V", (void *)native_init},
    101     {"update", "([B)V", (void *)native_update},
    102     {"digest", "()[B", (void *)native_digest},
    103     {"reset", "()V", (void *)native_reset},
    104 };
    105 
    106 int register_android_security_Md5MessageDigest(JNIEnv *env)
    107 {
    108     jclass clazz;
    109 
    110     clazz = env->FindClass("android/security/Md5MessageDigest");
    111     if (clazz == NULL) {
    112         LOGE("Can't find android/security/Md5MessageDigest");
    113         return -1;
    114     }
    115 
    116     fields.context = env->GetFieldID(clazz, "mNativeMd5Context", "I");
    117     if (fields.context == NULL) {
    118         LOGE("Can't find Md5MessageDigest.mNativeMd5Context");
    119         return -1;
    120     }
    121 
    122     return jniRegisterNativeMethods(env, "android/security/Md5MessageDigest",
    123         gMethods, NELEM(gMethods));
    124 }
    125 
    126 };
    127