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 28 using namespace android; 29 30 // ---------------------------------------------------------------------------- 31 32 struct fields_t { 33 jfieldID context; 34 }; 35 static fields_t fields; 36 37 static 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 51 static 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 64 static 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 95 static 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 117 static 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 126 int 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