我的Android
应用程序在特定设备上崩溃,但在我测试的其他所有设备上都能正常运行。我尝试在NDK中进行AES加密
设备名称:Telenor Infinity(本地供应商)
Android操作系统版本:6.0
以下是故障设备的错误日志:
04-15 23:11:42.815 6965-6965/? A/AEE/DEBUG: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'TELENOR/TELENOR_Infinity_i/TELENOR_Infinity_i:6.0/MRA58K/1471877097:user/release-keys'
Revision: '0'
ABI: 'arm'
04-15 23:11:42.816 6965-6965/? A/AEE/DEBUG: pid: 6896, tid: 6896, name: ker.sed.dms.app >>> com.tracker.sed.dms.app <<<
signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
04-15 23:11:42.845 6965-6965/? A/AEE/DEBUG: Abort message: 'stack corruption detected'
r0 00000000 r1 00001af0 r2 00000006 r3 b6feee2c
r4 b6feee34 r5 b6feede4 r6 00000002 r7 0000010c
r8 b4338f7d r9 b4736a00 sl beae9c90 fp b4736a00
ip 00000006 sp beae98e8 lr b6d57d4d pc b6d59408 cpsr 400b0010
04-15 23:11:42.861 6965-6965/? A/AEE/DEBUG: backtrace:
#00 pc 00042408 /system/lib/libc.so (tgkill+12)
#01 pc 00040d49 /system/lib/libc.so (pthread_kill+32)
#02 pc 0001c7eb /system/lib/libc.so (raise+10)
#03 pc 0001999d /system/lib/libc.so (__libc_android_abort+34)
#04 pc 00017550 /system/lib/libc.so (abort+4)
04-15 23:11:42.862 6965-6965/? A/AEE/DEBUG: #05 pc 0001b3ff /system/lib/libc.so (__libc_fatal+16)
#06 pc 000418bb /system/lib/libc.so (__stack_chk_fail+6)
#07 pc 00003acf /data/app/com.tracker.sed.dms.app-2/base.apk (offset 0x81c000)
#08 pc 00153130 /system/lib/libart.so (_ZN3art3Dbg13TagFromObjectERKNS_27ScopedObjectAccessUncheckedEPNS_6mirror6ObjectE.part.312+399)
#09 pc 0002ab4c /dev/ashmem/dalvik-main space (deleted)
aes_util.c
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include "aes.h"
#include "sha1.h"
#include "string.h"
//CRYPT CONFIG
#define MAX_LEN (2*1024*1024)
#define ENCRYPT 0
#define DECRYPT 1
#define AES_KEY_SIZE 128
#define READ_LEN 10
#define TARGET_CLASS "com/tracker/sed/dms/app/helpers/AES"
#define TARGET_CRYPT "crypt"
#define TARGET_CRYPT_SIG "([BLjava/lang/String;I)[B"
#define TARGET_CRYPT_SIMPLE "cryptSimple"
#define TARGET_CRYPT_SIMPLE_SIG "([BLjava/lang/String;I)[B"
#define TARGET_READ "read"
#define TARGET_READ_SIG "(Ljava/lang/String;J)[B"
/*
* Class: tv_fun_common_crypt_Funcrypt
* Method: sha1
* Signature: (Ljava/lang/String;JI)[Ljava/lang/Object;
*/
JNIEXPORT jbyteArray JNICALL android_native_aes(JNIEnv *env, jclass clazz,
jbyteArray jarray, jstring partialKey, jint jmode) {
unsigned char* pKey = (unsigned char*)(*env)->GetStringUTFChars(env, partialKey, 0);
unsigned int pKeylen = (unsigned int) ((*env)->GetStringLength(env, partialKey));
unsigned char copydatahere[128] = {0};
memcpy(copydatahere,AES_KEY1, sizeof(AES_KEY1));
memcpy(copydatahere + sizeof(AES_KEY1) ,pKey,pKeylen);
SHA1_CTX sha;
uint8_t results[20];
char *buf;
int n;
//char *shakey = {0};
char output[(sizeof(results) * 2) + 1];
char *ptr = &output[0];
buf = (char *) copydatahere;
n = strlen(buf);
SHA1Init(&sha);
SHA1Update(&sha, (uint8_t *)buf, n);
SHA1Final(results, &sha);
for (n = 0; n < 20; n++) {
ptr += sprintf(ptr, "%02x", results[n]);
}
unsigned char AES_KEY11[16] = {0};
memcpy(AES_KEY11,output,16);
//check input data
unsigned int len = (unsigned int) ((*env)->GetArrayLength(env, jarray));
if (len <= 0 || len >= MAX_LEN) {
return NULL;
}
unsigned char *data = (unsigned char*) (*env)->GetByteArrayElements(env,
jarray, NULL);
if (!data) {
return NULL;
}
unsigned int mode = (unsigned int) jmode;
unsigned int rest_len = len % AES_BLOCK_SIZE;
unsigned int padding_len = (
(ENCRYPT == mode) ? (AES_BLOCK_SIZE - rest_len) : 0);
unsigned int src_len = len + padding_len;
unsigned char *input = (unsigned char *) malloc(src_len);
memset(input, 0, src_len);
memcpy(input, data, len);
if (padding_len > 0) {
memset(input + len, (unsigned char) padding_len, padding_len);
}
(*env)->ReleaseByteArrayElements(env, jarray, data, 0);
unsigned char * buff = (unsigned char*) malloc(src_len);
if (!buff) {
free(input);
return NULL;
}
memset(buff, src_len, 0);
//set key & iv
unsigned int key_schedule[AES_BLOCK_SIZE * 4] = { 0 };
aes_key_setup(AES_KEY11, key_schedule, AES_KEY_SIZE);
//aes_key_setup(copydatahere, key_schedule, AES_KEY_SIZE);
if (mode == ENCRYPT) {
aes_encrypt_cbc(input, src_len, buff, key_schedule, AES_KEY_SIZE,
AES_KEY11);//AES_IV
} else {
aes_decrypt_cbc(input, src_len, buff, key_schedule, AES_KEY_SIZE,
AES_KEY11);//AES_IV
}
if (ENCRYPT != mode) {
unsigned char * ptr = buff;
ptr += (src_len - 1);
padding_len = (unsigned int) *ptr;
if (padding_len > 0 && padding_len <= AES_BLOCK_SIZE) {
src_len -= padding_len;
}
ptr = NULL;
}
jbyteArray bytes = (*env)->NewByteArray(env, src_len);
(*env)->SetByteArrayRegion(env, bytes, 0, src_len, (jbyte*) buff);
free(input);
free(buff);
return bytes;
}
JNIEXPORT jbyteArray JNICALL android_native_aes_simple(JNIEnv *env, jclass clazz,
jbyteArray jarray, jstring finalKey, jint jmode) {
unsigned char* fKey = (unsigned char*)(*env)->GetStringUTFChars(env, finalKey, 0);
unsigned char copydatahere[16] = {0};
memcpy(copydatahere ,fKey,16);
//check input data
unsigned int len = (unsigned int) ((*env)->GetArrayLength(env, jarray));
if (len <= 0 || len >= MAX_LEN) {
return NULL;
}
unsigned char *data = (unsigned char*) (*env)->GetByteArrayElements(env,
jarray, NULL);
if (!data) {
return NULL;
}
unsigned int mode = (unsigned int) jmode;
unsigned int rest_len = len % AES_BLOCK_SIZE;
unsigned int padding_len = (
(ENCRYPT == mode) ? (AES_BLOCK_SIZE - rest_len) : 0);
unsigned int src_len = len + padding_len;
unsigned char *input = (unsigned char *) malloc(src_len);
memset(input, 0, src_len);
memcpy(input, data, len);
if (padding_len > 0) {
memset(input + len, (unsigned char) padding_len, padding_len);
}
(*env)->ReleaseByteArrayElements(env, jarray, data, 0);
unsigned char * buff = (unsigned char*) malloc(src_len);
if (!buff) {
free(input);
return NULL;
}
memset(buff, src_len, 0);
//set key & iv
unsigned int key_schedule[AES_BLOCK_SIZE * 4] = { 0 };
aes_key_setup(copydatahere, key_schedule, AES_KEY_SIZE);
//aes_key_setup(copydatahere, key_schedule, AES_KEY_SIZE);
if (mode == ENCRYPT) {
aes_encrypt_cbc(input, src_len, buff, key_schedule, AES_KEY_SIZE,
copydatahere);//AES_IV
} else {
aes_decrypt_cbc(input, src_len, buff, key_schedule, AES_KEY_SIZE,
copydatahere);//AES_IV
}
if (ENCRYPT != mode) {
unsigned char * ptr = buff;
ptr += (src_len - 1);
padding_len = (unsigned int) *ptr;
if (padding_len > 0 && padding_len <= AES_BLOCK_SIZE) {
src_len -= padding_len;
}
ptr = NULL;
}
jbyteArray bytes = (*env)->NewByteArray(env, src_len);
(*env)->SetByteArrayRegion(env, bytes, 0, src_len, (jbyte*) buff);
free(input);
free(buff);
return bytes;
}
JNIEXPORT jbyteArray JNICALL android_native_read(JNIEnv *env, jclass clazz,
jstring jstr, jlong jtimestam) {
char * path = (char *) (*env)->GetStringUTFChars(env, jstr, NULL);
if (!path) {
return NULL;
}
FILE *fp = fopen(path, "r");
if (!fp) {
return NULL;
}
(*env)->ReleaseStringUTFChars(env, jstr, path);
char pBuf[READ_LEN + 1] = { 0 };
fread(pBuf, 1, READ_LEN, fp);
pBuf[READ_LEN] = 0;
fclose(fp);
jbyteArray bytes = (*env)->NewByteArray(env, READ_LEN);
(*env)->SetByteArrayRegion(env, bytes, 0, READ_LEN, (jbyte*) pBuf);
return bytes;
}
static const JNINativeMethod gMethods[] = { { TARGET_CRYPT, TARGET_CRYPT_SIG,
(void*) android_native_aes },
{ TARGET_CRYPT_SIMPLE, TARGET_CRYPT_SIMPLE_SIG,
(void*) android_native_aes_simple },
{ TARGET_READ, TARGET_READ_SIG,
(void*) android_native_read } };
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEnv* env = NULL;
if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
return -1;
}
jclass clazz = (*env)->FindClass(env, TARGET_CLASS);
if (!clazz) {
return -1;
}
if ((*env)->RegisterNatives(env, clazz, gMethods,
sizeof(gMethods) / sizeof(gMethods[0])) != JNI_OK) {
return -1;
}
return JNI_VERSION_1_4;
}
JNIEXPORT void JNICALL JNI_OnUnload(JavaVM* vm, void* reserved) {
JNIEnv* env = NULL;
if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
return;
}
}
检测到堆栈损坏。我无法理解为什么它适用于所有其他设备并且在特定设备上失败。 帮助我解决问题。
答案
通过增加copydatahere的大小[128]问题得到了解决:)
感谢 Michael Walz 确定问题