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