问题背景
项目中在开发加密T卡,加密T卡和上位机通信的方式是在T卡上虚拟出文件,然后上位机通过读写该文件和加密T卡进行通信,在安卓手机上使用加密T卡的时候,出现一个问题,通过安卓的java层文件流的方式打开加密T卡中的文件,然后读出的数据都是0,和加密T卡根本通信不起来。
问题分析
1首先在windows上正常openfile ,然后readfile可以正常读取加密T卡发过来的数据。
2 使用linux系统,和安卓问题一致,可能安卓底层就是linux原因。
3 linux在内核层会有文件系统的缓冲,也就是使用read和write操作文件的时候,不会立马从磁盘写入和读出,而是内存中的缓冲,所以需要用到direct IO,直接和磁盘通信。
解决方式
1 安卓层采用JNI的方式来操作加密T卡中的文件
JNI 接口:
extern "C"
JNIEXPORT jboolean JNICALL Java_com_csizg_tfwrtest_libwrtest_SKFNative_readFile
(JNIEnv *env, jclass jObj, jstring jfilePath, jint jreadBlockSize, jbyteArray joutData, jint joutDataLen) {
int ret = -1;
const char *filePath = NULL;
UINT readBlockSize, outDataLen;
BYTE *outData;
if (jfilePath != NULL) {
filePath = (env)->GetStringUTFChars(jfilePath, FALSE);
} else {
return FALSE;
}
readBlockSize = jIntToUINT(jreadBlockSize);
outDataLen = jIntToUINT(joutDataLen);
if (joutData != NULL) {
outData = (BYTE *) (env)->GetPrimitiveArrayCritical(joutData, NULL);
if (outData == NULL) {
return FALSE;
}
}
ret = tf_read(filePath, outData, outDataLen);
if (ret < 0) {
return FALSE;
}
(env)->ReleasePrimitiveArrayCritical(joutData, outData, JNI_ABORT);
return TRUE;
}
2 在open文件的时候,指定O_DIRECT标志。
fd1 = open(path_w, O_WRONLY | O_CREAT | O_NOCTTY | O_DIRECT);
if (fd1 < 0) {
LOGC_ERROR("dev1 open:");
fd1 = -1;
return -1;
}
3 因为direct IO的特点,需要用户层的缓冲buff的地址以及大小都要和存储块大小对齐。具体原因讲解可以参考如下博文:
https://blog.csdn.net/yang15225094594/article/details/43268133
buff对齐源码:
struct stat fstat_w;
stat(path_w, &fstat_w);
int blksize_w = (int) fstat_w.st_blksize;
int align_w = blksize_w - 1;
const char *buff_w = (char *) malloc((int) blksize_w + align_w);
send_data_buffer = (char *) (((unsigned long int) buff_w + align_w) & ~((unsigned long int) align_w));
4 如果用户缓冲buff和存储块不对齐,read和write的时候,会报地址错误的error。
5 安卓JNI和direct IO 完整源码如下:
https://download.csdn.net/download/qq_39952971/18197909
测试结果
安卓手机通过JNI的方式open、read、write 加密T卡中的通信文件,可以实现利用加密T卡进行SM4加密流程,加密后的数据和其它SM4工具对比,结果一致。
plain data
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
enc data
ad c1 4 5a 98 9 9 3f fc 9 d6 c5 f5 ce e3 81
ad c1 4 5a 98 9 9 3f fc 9 d6 c5 f5 ce e3 81
ad c1 4 5a 98 9 9 3f fc 9 d6 c5 f5 ce e3 81
ad c1 4 5a 98 9 9 3f fc 9 d6 c5 f5 ce e3 81
ad c1 4 5a 98 9 9 3f fc 9 d6 c5 f5 ce e3 81
ad c1 4 5a 98 9 9 3f fc 9 d6 c5 f5 ce e3 81
ad c1 4 5a 98 9 9 3f fc 9 d6 c5 f5 ce e3 81
ad c1 4 5a 98 9 9 3f fc 9 d6 c5 f5 ce e3 81
ad c1 4 5a 98 9 9 3f fc 9 d6 c5 f5 ce e3 81
ad c1 4 5a 98 9 9 3f fc 9 d6 c5 f5 ce e3 81
ad c1 4 5a 98 9 9 3f fc 9 d6 c5 f5 ce e3 81
ad c1 4 5a 98 9 9 3f fc 9 d6 c5 f5 ce e3 81
ad c1 4 5a 98 9 9 3f fc 9 d6 c5 f5 ce e3 81
ad c1 4 5a 98 9 9 3f fc 9 d6 c5 f5 ce e3 81
ad c1 4 5a 98 9 9 3f fc 9 d6 c5 f5 ce e3 81
ad c1 4 5a 98 9 9 3f fc 9 d6 c5 f5 ce e3 81