diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..6fb18a0 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,54 @@ +plugins { + id 'com.android.application' +} + +android { + compileSdk 32 + + defaultConfig { + applicationId "com.xypower.secapp" + minSdk 28 + targetSdk 28 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + externalNativeBuild { + cmake { + cppFlags '' + arguments "-DANDROID_STL=c++_shared" + abiFilters 'arm64-v8a' + } + } + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + externalNativeBuild { + cmake { + path file('src/main/cpp/CMakeLists.txt') + version '3.18.1' + } + } + buildFeatures { + viewBinding true + } +} + +dependencies { + + implementation 'com.android.support:appcompat-v7:28.0.0' + implementation 'com.android.support.constraint:constraint-layout:2.0.4' + testImplementation 'junit:junit:4.13.2' + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' + implementation files('libs/dsdevicesdk1.3.aar') +} \ No newline at end of file diff --git a/app/libs/dsdevicesdk1.3.aar b/app/libs/dsdevicesdk1.3.aar new file mode 100644 index 0000000..6f5d0e1 Binary files /dev/null and b/app/libs/dsdevicesdk1.3.aar differ diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/release/output-metadata.json b/app/release/output-metadata.json new file mode 100644 index 0000000..0a55799 --- /dev/null +++ b/app/release/output-metadata.json @@ -0,0 +1,20 @@ +{ + "version": 3, + "artifactType": { + "type": "APK", + "kind": "Directory" + }, + "applicationId": "com.xypower.secapp", + "variantName": "release", + "elements": [ + { + "type": "SINGLE", + "filters": [], + "attributes": [], + "versionCode": 1, + "versionName": "1.0", + "outputFile": "app-release.apk" + } + ], + "elementType": "File" +} \ No newline at end of file diff --git a/app/src/androidTest/java/com/xinyingpower/myapplication/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/xinyingpower/myapplication/ExampleInstrumentedTest.java new file mode 100644 index 0000000..a4e1550 --- /dev/null +++ b/app/src/androidTest/java/com/xinyingpower/myapplication/ExampleInstrumentedTest.java @@ -0,0 +1,25 @@ +package com.xypower.secapp; + +import android.content.Context; +import android.support.test.InstrumentationRegistry; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + assertEquals("com.xinyingpower.myapplication", appContext.getPackageName()); + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..76d5df9 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt new file mode 100644 index 0000000..c41a455 --- /dev/null +++ b/app/src/main/cpp/CMakeLists.txt @@ -0,0 +1,61 @@ +# For more information about using CMake with Android Studio, read the +# documentation: https://d.android.com/studio/projects/add-native-code.html + +# Sets the minimum version of CMake required to build the native library. + +cmake_minimum_required(VERSION 3.18.1) + + +IF (CMAKE_BUILD_TYPE STREQUAL Debug) + ADD_DEFINITIONS(-D_DEBUG) +ELSE() + ADD_DEFINITIONS(-DNDEBUG) +ENDIF() +# add_definitions(-DBOOST_EXCEPTION_DISABLE) +# add_definitions(-DBOOST_NO_EXCEPTIONS) +add_definitions(-DTERMINAL_CLIENT) +add_definitions(-DUSING_NRSEC) + + +# Declares and names the project. +project("secapp") + +# Creates and names a library, sets it as either STATIC +# or SHARED, and provides the relative paths to its source code. +# You can define multiple libraries, and CMake builds them for you. +# Gradle automatically packages shared libraries with your APK. + +add_library( # Sets the name of the library. + secapp + + # Sets the library as a shared library. + SHARED + + # Provides a relative path to your source file(s). + NrsecPort.cpp + SpiPort.cpp + native-lib.cpp ) + +# Searches for a specified prebuilt library and stores the path as a +# variable. Because CMake includes system libraries in the search path by +# default, you only need to specify the name of the public NDK library +# you want to add. CMake verifies that the library exists before +# completing its build. + +find_library( # Sets the name of the path variable. + log-lib + + # Specifies the name of the NDK library that + # you want CMake to locate. + log ) + +# Specifies libraries CMake should link to your target library. You +# can link multiple libraries, such as libraries you define in this +# build script, prebuilt third-party libraries, or system libraries. + +target_link_libraries( # Specifies the target library. + secapp + + # Links the target library to the log library + # included in the NDK. + ${log-lib} ) \ No newline at end of file diff --git a/app/src/main/cpp/NrsecPort.cpp b/app/src/main/cpp/NrsecPort.cpp new file mode 100644 index 0000000..eea696d --- /dev/null +++ b/app/src/main/cpp/NrsecPort.cpp @@ -0,0 +1,1261 @@ +#include "NrsecPort.h" +#ifdef __ANDROID__ +#include +#endif + +#define RE_SUC 0x01 +#define RE_ERROR 0x00 + +#define TAG_SPI "SPI" + +const uint8_t EK_CMD[5] = { 0x80,0xd4,0x01,0x00,0x10 }; +const uint8_t AK_CMD[5] = { 0x80,0xd4,0x02,0x00,0x10 }; +const uint8_t IV_CMD[5] = { 0x80,0xd4,0x04,0x00,0x10 }; +uint8_t SM1Encrypt_CMD[5] = { 0xa0,0xe0,0x80,0xff,0xff }; +uint8_t SM1decoder_CMD[5] = { 0xa0,0xe0,0x81,0xff,0xff }; +uint8_t SM2Keypair_CMD[5] = { 0x80,0xb2,0x00,0xff,0x00 }; +uint8_t SM2OutPub_CMD[5] = { 0x80,0xb8,0x01,0xff,0x40 }; +uint8_t SM2OutPri_CMD[5] = { 0x80,0xb8,0x02,0xff,0x20 }; +uint8_t SM2InPub_CMD[5] = { 0x80,0xba,0x01,0xff,0x40 }; +uint8_t SM2InPri_CMD[5] = { 0x80,0xba,0x02,0xff,0x20 }; +uint8_t SM3Hash_CMD[5] = { 0x80,0xb5,0x00,0xff,0xff }; +uint8_t SM2Sign_CMD[5] = { 0x80,0xb4,0x00,0xff,0x20 }; +uint8_t SM2VerifySign_CMD[5] = { 0x80,0xb6,0x00,0xff,0x60 }; +uint8_t SM2encrypt_CMD[5] = { 0x80,0xb3,0x01,0xff,0x20 }; +uint8_t SM2decoder_CMD[5] = { 0x80,0xb3,0x81,0xff,0x80 }; +uint8_t SM2cert_CMD[5] = { 0x80,0xb7,0xff,0xff,0xff }; +uint8_t Random_CMD[5] = { 0x00,0x84,0x00,0x00,0xff }; +const uint8_t Version_CMD[5] = { 0x00,0x5b,0x00,0x00,0x40 }; +const uint8_t Indentify_CMD[5] = { 0x80,0xb3,0x01,0x04,0x20 }; + +uint8_t NrsecPort::CalcCRC7(const uint8_t *buff, int len) +{ + const static uint8_t crc7_table[256] = { + 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, + 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77, + 0x19, 0x10, 0x0b, 0x02, 0x3d, 0x34, 0x2f, 0x26, + 0x51, 0x58, 0x43, 0x4a, 0x75, 0x7c, 0x67, 0x6e, + 0x32, 0x3b, 0x20, 0x29, 0x16, 0x1f, 0x04, 0x0d, + 0x7a, 0x73, 0x68, 0x61, 0x5e, 0x57, 0x4c, 0x45, + 0x2b, 0x22, 0x39, 0x30, 0x0f, 0x06, 0x1d, 0x14, + 0x63, 0x6a, 0x71, 0x78, 0x47, 0x4e, 0x55, 0x5c, + 0x64, 0x6d, 0x76, 0x7f, 0x40, 0x49, 0x52, 0x5b, + 0x2c, 0x25, 0x3e, 0x37, 0x08, 0x01, 0x1a, 0x13, + 0x7d, 0x74, 0x6f, 0x66, 0x59, 0x50, 0x4b, 0x42, + 0x35, 0x3c, 0x27, 0x2e, 0x11, 0x18, 0x03, 0x0a, + 0x56, 0x5f, 0x44, 0x4d, 0x72, 0x7b, 0x60, 0x69, + 0x1e, 0x17, 0x0c, 0x05, 0x3a, 0x33, 0x28, 0x21, + 0x4f, 0x46, 0x5d, 0x54, 0x6b, 0x62, 0x79, 0x70, + 0x07, 0x0e, 0x15, 0x1c, 0x23, 0x2a, 0x31, 0x38, + 0x41, 0x48, 0x53, 0x5a, 0x65, 0x6c, 0x77, 0x7e, + 0x09, 0x00, 0x1b, 0x12, 0x2d, 0x24, 0x3f, 0x36, + 0x58, 0x51, 0x4a, 0x43, 0x7c, 0x75, 0x6e, 0x67, + 0x10, 0x19, 0x02, 0x0b, 0x34, 0x3d, 0x26, 0x2f, + 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c, + 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, + 0x6a, 0x63, 0x78, 0x71, 0x4e, 0x47, 0x5c, 0x55, + 0x22, 0x2b, 0x30, 0x39, 0x06, 0x0f, 0x14, 0x1d, + 0x25, 0x2c, 0x37, 0x3e, 0x01, 0x08, 0x13, 0x1a, + 0x6d, 0x64, 0x7f, 0x76, 0x49, 0x40, 0x5b, 0x52, + 0x3c, 0x35, 0x2e, 0x27, 0x18, 0x11, 0x0a, 0x03, + 0x74, 0x7d, 0x66, 0x6f, 0x50, 0x59, 0x42, 0x4b, + 0x17, 0x1e, 0x05, 0x0c, 0x33, 0x3a, 0x21, 0x28, + 0x5f, 0x56, 0x4d, 0x44, 0x7b, 0x72, 0x69, 0x60, + 0x0e, 0x07, 0x1c, 0x15, 0x2a, 0x23, 0x38, 0x31, + 0x46, 0x4f, 0x54, 0x5d, 0x62, 0x6b, 0x70, 0x79 + }; + + uint8_t crc7_accum = 0; + int i; + + for (i = 0; i < len; i++) { + crc7_accum = + crc7_table[(crc7_accum << 1) ^ buff[i]]; + } + return crc7_accum; +} + +void NrsecPort::SendCMD(uint8_t* cmd, uint8_t* rxbuf) +{ + int i = 0; + int retval; + +#if defined (CONFIG_ATMEL_SPI_DEBUG) + printf("tx %1d bytes: ", CMD_HEAD_SIZE); + for (i = 0; i < CMD_HEAD_SIZE; i++) + { + printf(" %02x", cmd[i]); + } + printf("\n"); +#endif + + /* send five command header */ + for (i = 0; i < CMD_HEAD_SIZE; i++) + { + retval = spi_transfer(cmd + i, rxbuf + i, 1); +#ifdef __ANDROID__ + __android_log_print(ANDROID_LOG_INFO, TAG_SPI, "cmd[%d]=%x,rxbuf[%d]=%x", i, *(cmd + i), i, *(rxbuf + i)); +#endif + delay(20); + } + + cmd[0] = 0xaa; //for response +} + +void NrsecPort::RcvINS(uint8_t* txbuf, uint8_t* buf, uint8_t ins) +{ + int retval; + int cnt = 5000; + /* receive ins */ +INS: + txbuf[0] = 0xaa; + //delay(1000); + while (cnt--) + { + retval = spi_transfer(txbuf, buf, 1); +#ifdef __ANDROID__ + __android_log_print(ANDROID_LOG_INFO, TAG_SPI, "RcvINS txbuf=%x,buf=%x", *txbuf, *buf); +#endif + if (*buf == ins) + { + return; + break; + } + else + { + delay(1000); + } + } +} + +void NrsecPort::RcvLEN(uint8_t* txbuf, uint8_t* buf, uint8_t len) +{ + int retval; + /* receive length */ +LEN: + for (int i = 0; i < len; i++) { + txbuf[0] = 0xaa; + retval = spi_transfer(txbuf, buf + i, 1); +#ifdef __ANDROID__ + __android_log_print(ANDROID_LOG_INFO, TAG_SPI, "RecvLEN txbuf=%x,rxbuf=%x", *txbuf, *(buf + i)); +#endif + } +} + +//Rcvdata +void NrsecPort::RcvData(uint8_t*txbuf, uint8_t* buf) +{ + int len = *(buf - 1); + RcvData(txbuf, buf, len); +} + +void NrsecPort::RcvData(uint8_t*txbuf, uint8_t*buf, int len) +{ + int i; + int retval; + + for (i = 0; i < len; i++) + { + *(txbuf + i) = 0xaa; + } + + /* receive data and crc */ + for (i = 0; i < len; i++) + { + retval = spi_transfer(txbuf, buf + i, 1); + //__android_log_print(ANDROID_LOG_INFO, TAG_SPI, "RcvData data[%d]=%x", i, *(buf + i)); + } + +} + +//RcvSW +void NrsecPort::RcvSW(uint8_t*txbuf, uint8_t*buf, uint8_t sw) +{ + int i; + int retval; + +SW90: + /* receive state word */ + delay(20);//20 + while (1) + { + retval = spi_transfer(txbuf, buf, 1); +#ifdef __ANDROID__ + __android_log_print(ANDROID_LOG_INFO, TAG_SPI, "RecvSW txbuf=%x,buf=%x", *txbuf, *buf); +#endif + if (*buf != sw) + { + goto SW90; + } + break; + } + retval = spi_transfer(txbuf, buf + 1, 1); +} + +void NrsecPort::SendEnd(uint8_t* txbuf, uint8_t* buf) +{ + int retval; + txbuf[0] = 0xaa; + retval = spi_transfer(txbuf, buf, 1); +#ifdef __ANDROID__ + __android_log_print(ANDROID_LOG_INFO, TAG_SPI, "SendEnd txbuf=%x,rxbuf=%hhu", *txbuf, *buf); +#endif +} + +void NrsecPort::SendId(uint8_t* txbuf, uint8_t* buf, uint8_t id) +{ + int retval; + txbuf[0] = id; + retval = spi_transfer(txbuf, buf, 1); +#ifdef __ANDROID__ + __android_log_print(ANDROID_LOG_INFO, TAG_SPI, "SendID txbuf=%x,rxbuf=%hhu", *txbuf, *buf); +#endif +} + +void NrsecPort::SendData(uint8_t* data, uint8_t* rxbuf, int data_size) +{ + int i = 0; + int retval; + uint8_t crc[1]; + crc[0] = CalcCRC7(data, data_size); + + for (i = 0; i < data_size; i++) + { + retval = spi_transfer(data + i, rxbuf + i, 1); +#ifdef __ANDROID__ + __android_log_print(ANDROID_LOG_INFO, TAG_SPI, "SendData i=%d,txbuf=%x,rxbuf=%x", i, *(data + i), *(rxbuf + i)); +#endif + delay(20); + } + retval = spi_transfer(crc, rxbuf, 1); +} + +int NrsecPort::SM1ImportKey(const uint8_t* ek, const uint8_t* ak) +{ + int i; + int cnt; + uint8_t txbuf[256]; + uint8_t rxbuf[256]; + + int retval; + int msglen; + + cnt = 0; + msglen = 5; + memset(rxbuf, 0, sizeof(rxbuf)); + memset(txbuf, 0, sizeof(txbuf)); + + CMD_RESEND: + + memcpy(txbuf, (const void *)EK_CMD, sizeof(EK_CMD)); + + SendCMD(txbuf, rxbuf); + + RcvINS(txbuf, rxbuf, txbuf[1]); // 指令 + + SendId(txbuf, rxbuf, 0x55); + + memcpy(txbuf, ek, 16); +// txbuf[16] = CalcCRC7(ek, 16); + + SendData(txbuf, rxbuf, 16); + + RcvSW(txbuf, rxbuf, 0x90); + + memcpy(txbuf, (const void *)AK_CMD, sizeof(AK_CMD)); + + SendCMD(txbuf, rxbuf); + + RcvINS(txbuf, rxbuf, txbuf[1]); // 指令 + + SendId(txbuf, rxbuf, 0x55); + + memcpy(txbuf, ak, 16); +// txbuf[16] = CalcCRC7(ak, 16); + + SendData(txbuf, rxbuf, 16);//senddata函数中已经包含crc了 + + SendEnd(txbuf, rxbuf); + + RcvSW(txbuf, rxbuf, 0x90); + + return 0; +} + +int NrsecPort::ImportIV(const uint8_t* iv, uint8_t ivLength) +{ + int i; + int cnt; + uint8_t txbuf[256]; + uint8_t rxbuf[256]; + + int retval; + int msglen; + + cnt = 0; + msglen = 5; + memset(rxbuf, 0, sizeof(rxbuf)); + memset(txbuf, 0, sizeof(txbuf)); + +CMD_RESEND: + + memcpy(txbuf, (const void *)IV_CMD, sizeof(IV_CMD)); + + SendCMD(txbuf, rxbuf); + + RcvINS(txbuf, rxbuf, txbuf[1]); // 指令 + + SendId(txbuf, rxbuf, 0x55); + + memcpy(txbuf, iv, ivLength); +// txbuf[ivLength] = CalcCRC7(iv, ivLength); + + SendData(txbuf, rxbuf, ivLength); + + SendEnd(txbuf, rxbuf); + + RcvSW(txbuf, rxbuf, 0x90); + + return 0; +} + +int NrsecPort::SM1Encrypt(const uint8_t* data, uint16_t dataLen, uint8_t* encryptedData, uint16_t* bufferLen) +{ + int i; + int cnt; + uint8_t txbuf[2048]; + uint8_t rxbuf[2048]; + + int retval; + int msglen; + + cnt = 0; + msglen = 5; + memset(rxbuf, 0, sizeof(rxbuf)); + memset(txbuf, 0, sizeof(txbuf)); + + //printf("tx %1d bytes: ", msglen); + + CMD_RESEND: + + memcpy(txbuf, (const void *)SM1Encrypt_CMD, sizeof(SM1Encrypt_CMD)); + + txbuf[3] = dataLen >> 8; + txbuf[4] = dataLen & 0xFF; + + SendCMD(txbuf, rxbuf); + + //SendEnd(txbuf,rxbuf);//遇到长度的0xe0数据 + + RcvINS(txbuf, rxbuf, txbuf[1]); // 指令 + + SendId(txbuf, rxbuf, 0x55); + + memcpy(txbuf,data,dataLen); + + SendData(txbuf,rxbuf,dataLen); + + SendEnd(txbuf,rxbuf); + + RcvINS(txbuf,rxbuf,0xe0); + + RcvLEN(txbuf, rxbuf + 1, 2); //长度 多加一个字节的 CRC + +// uint8_t len = *(rxbuf + 1); + uint16_t len =(*(rxbuf+1)<<8) + (*(rxbuf+2)); + + RcvData(txbuf, rxbuf + 3, len); + + RcvSW(txbuf, rxbuf + 3 + len, 0x90); + + //计算接收到数据的CRC + //__android_log_print(ANDROID_LOG_INFO, TAG_SPI, "Calcac = %x", CalcCRC7(rxbuf + 3, len-1)); + if (CalcCRC7(rxbuf + 3, len-1) != rxbuf[len + 2]) + { + //CRC Error 命令重发,超过3次,结束 + if (cnt < 3) + { + cnt++; + goto CMD_RESEND; + printf("cnt over\n"); + } + else + { + printf("ERROR\n"); + } + } + + // printf("rx %1d bytes: ", rxbuf[1] + 4); +#ifdef __ANDROID__ + __android_log_print(ANDROID_LOG_INFO, TAG_SPI, "rx %1d bytes:", rxbuf[1] + 4); +#endif + + memcpy(encryptedData, rxbuf + 3, len-1); + //memcpy(&bufferLen, &len-1, 1); + * bufferLen = len -1; + return 0; +} + +int NrsecPort::SM1Decrypt(const uint8_t* encryptedData, uint16_t encryptedDataLen, uint8_t* data, uint16_t* bufferLen) +{ + int i; + int cnt; + uint8_t txbuf[2048];//256 + uint8_t rxbuf[2048];//256 + + int retval; + int msglen; + + cnt = 0; + msglen = 5; + memset(rxbuf, 0, sizeof(rxbuf)); + memset(txbuf, 0, sizeof(txbuf)); + + //printf("tx %1d bytes: ", msglen); + + CMD_RESEND: + + memcpy(txbuf, (const void *)SM1decoder_CMD, sizeof(SM1decoder_CMD)); + + txbuf[3] = encryptedDataLen >> 8; + txbuf[4] = encryptedDataLen & 0xFF; + + SendCMD(txbuf, rxbuf); + + //SendEnd(txbuf,rxbuf); + + RcvINS(txbuf, rxbuf, txbuf[1]); // 指令 + + SendId(txbuf, rxbuf, 0x55); + + memcpy(txbuf,encryptedData,encryptedDataLen); + + SendData(txbuf,rxbuf,encryptedDataLen); + + SendEnd(txbuf,rxbuf); + + RcvINS(txbuf,rxbuf,0xe0); + + RcvLEN(txbuf, rxbuf + 1, 2); //长度 多加一个字节的 CRC + +// uint8_t len = *(rxbuf + 1); + uint16_t len =(*(rxbuf+1)<<8) + (*(rxbuf+2)); + + RcvData(txbuf, rxbuf + 3, len); + + RcvSW(txbuf, rxbuf + 3 + len, 0x90); + + //计算接收到数据的CRC + //__android_log_print(ANDROID_LOG_INFO, TAG_SPI, "Calcac = %x", CalcCRC7(rxbuf + 3, len-1)); + if (CalcCRC7(rxbuf + 3, len-1) != rxbuf[len + 2]) + { + //CRC Error 命令重发,超过3次,结束 + if (cnt < 3) + { + cnt++; + goto CMD_RESEND; + printf("cnt over\n"); + } + else + { + printf("ERROR\n"); + } + } + + // printf("rx %1d bytes: ", rxbuf[1] + 4); +#ifdef __ANDROID__ + __android_log_print(ANDROID_LOG_INFO, TAG_SPI, "rx %1d bytes:", rxbuf[1] + 4); +#endif + + memcpy(data, rxbuf + 3, len-1); + //memcpy(&bufferLen, &len-1, 1); + * bufferLen = len -1; + return 0; +} + +int NrsecPort::Random(uint8_t* output, uint8_t length) +{ + int i; + int cnt; + uint8_t txbuf[256]; + uint8_t rxbuf[256]; + + int retval; + int msglen; + + cnt = 0; + msglen = 5; + memset(rxbuf, 0, sizeof(rxbuf)); + memset(txbuf, 0, sizeof(txbuf)); + + //printf("tx %1d bytes: ", msglen); + +CMD_RESEND: + + memcpy(txbuf, (const void *)Random_CMD, sizeof(Random_CMD)); + + txbuf[4] = length; + + SendCMD(txbuf, rxbuf); + + RcvINS(txbuf, rxbuf, txbuf[1]); // 指令 + + RcvLEN(txbuf, rxbuf + 1, 1); //长度 多加一个字节的 CRC + + uint8_t len = *(rxbuf + 1); + + RcvData(txbuf, rxbuf + 2, len); + + RcvSW(txbuf, rxbuf + 2 + len, 0x90); + + //计算接收到数据的CRC + if (CalcCRC7(rxbuf + 2, rxbuf[1] - 1) != rxbuf[rxbuf[1] + 1]) + { + //CRC Error 命令重发,超过3次,结束 + if (cnt < 3) + { + cnt++; + goto CMD_RESEND; + printf("cnt over\n"); + } + else + { + printf("ERROR\n"); + } + } + + // printf("rx %1d bytes: ", rxbuf[1] + 4); +#ifdef __ANDROID__ + __android_log_print(ANDROID_LOG_INFO, TAG_SPI, "rx %1d bytes:", rxbuf[1] + 4); +#endif + + memcpy(output, rxbuf + 2, len-1); + + return 0; +} + +std::string NrsecPort::Version() +{ + int i; + int cnt; + uint8_t txbuf[256]; + uint8_t rxbuf[256]; + + int retval; + int msglen; + + cnt = 0; + msglen = 5; + memset(rxbuf, 0, sizeof(rxbuf)); + memset(txbuf, 0, sizeof(txbuf)); + + //printf("tx %1d bytes: ", msglen); + //__android_log_print(ANDROID_LOG_INFO, TAG_SPI, "tx %1d bytes", msglen); + +CMD_RESEND: + + memcpy(txbuf, Version_CMD, sizeof(Version_CMD)); + + SendCMD(txbuf, rxbuf); + + RcvINS(txbuf, rxbuf, txbuf[1]); // 指令 + + // txbuf[4] = 0xAA; + RcvLEN(txbuf, rxbuf + 1, 1); //长度 多加一个字节的 CRC + + int dataLen = *(rxbuf + 1); + + RcvData(txbuf, rxbuf + 2, dataLen); + + RcvSW(txbuf, rxbuf + 2 + rxbuf[1], 0x90); + + //计算接收到数据的CRC + if (CalcCRC7(rxbuf + 2, rxbuf[1] - 1) != rxbuf[rxbuf[1] + 1]) + { + //CRC Error 命令重发,超过3次,结束 + if (cnt < 3) + { + cnt++; + goto CMD_RESEND; + printf("cnt over\n"); + } + else + { + printf("ERROR\n"); + } + } + + //printf("rx %1d bytes: ", rxbuf[1]+4); +#ifdef __ANDROID__ + __android_log_print(ANDROID_LOG_INFO, TAG_SPI, "rx %1d bytes:", rxbuf[1] + 4); +#endif + std::string version = ""; + char output[16] = { 0 }; + for (i = 0; i < dataLen-1; i++) { + if (*(rxbuf + 2 + i) == 0) { + break; + } + snprintf(output, sizeof(output), "%c", *(rxbuf + 2 + i)); + version += output; + } +#ifdef __ANDROID__ + __android_log_print(ANDROID_LOG_INFO, TAG_SPI, "Version: %s", version.c_str()); +#endif + //__android_log_print(ANDROID_LOG_INFO, "SPi", "%s", rxbuf); + // printf("\n"); + + + return version; +} + +int NrsecPort::SM2keypair(int index)//产生密钥 +{ + int i; + int cnt; + uint8_t txbuf[256]; + uint8_t rxbuf[256]; + + int retval; + int msglen; + + msglen = 5; + memset(rxbuf, 0, sizeof(rxbuf)); + memset(txbuf, 0, sizeof(txbuf)); + + SM2Keypair_CMD[3] = index; + + //printf("tx %1d bytes: ", msglen); + //__android_log_print(ANDROID_LOG_INFO, TAG_SPI, "tx %1d bytes", msglen); + +CMD_RESEND: + + memcpy(txbuf, (const void *)SM2Keypair_CMD, sizeof(SM2Keypair_CMD)); + + SendCMD(txbuf, rxbuf); + + RcvSW(txbuf, rxbuf, 0x90); + + + + return 0; +} + +int NrsecPort::SM2ExportPublicKey(int index, uint8_t result[], uint8_t * len)//导出公钥 +{ + int i; + int cnt; + uint8_t txbuf[256]; + uint8_t rxbuf[256]; + + int retval; + int msglen; + + cnt = 0; + msglen = 5; + memset(rxbuf, 0, sizeof(rxbuf)); + memset(txbuf, 0, sizeof(txbuf)); + + SM2OutPub_CMD[3] = index; + + +CMD_RESEND: + + memcpy(txbuf, (const void *)SM2OutPub_CMD, sizeof(SM2OutPub_CMD)); + + SendCMD(txbuf, rxbuf); + + RcvINS(txbuf, rxbuf, txbuf[1]); // 指令 + + RcvLEN(txbuf, rxbuf + 1, 1); //长度 多加一个字节的 CRC + + RcvData(txbuf, rxbuf + 2); + + RcvSW(txbuf, rxbuf + 2 + rxbuf[1], 0x90); + + //计算接收到数据的CRC + if (CalcCRC7(rxbuf + 2, rxbuf[1] - 1) != rxbuf[rxbuf[1] + 1]) + { + //CRC Error 命令重发,超过3次,结束 + if (cnt < 3) + { + cnt++; + goto CMD_RESEND; + printf("cnt over\n"); + } + else + { + printf("ERROR\n"); + } + } + + //printf("rx %1d bytes: ", rxbuf[1]+4); +#ifdef __ANDROID__ + __android_log_print(ANDROID_LOG_INFO, TAG_SPI, "rx %1d bytes:", rxbuf[1] + 4); +#endif + memcpy(result, rxbuf + 2, rxbuf[1]-1); + * len = rxbuf[1]-1; + return 0; +} + +int NrsecPort::SM2ExportPrivateKey(int index, uint8_t result[],uint8_t * len)//导出私钥 +{ + int i; + int cnt; + uint8_t txbuf[256]; + uint8_t rxbuf[256]; + + int retval; + int msglen; + + cnt = 0; + msglen = 5; + memset(rxbuf, 0, sizeof(rxbuf)); + memset(txbuf, 0, sizeof(txbuf)); + + SM2OutPri_CMD[3] = index; + + //printf("tx %1d bytes: ", msglen); + //__android_log_print(ANDROID_LOG_INFO, TAG_SPI, "tx %1d bytes", msglen); + +CMD_RESEND: + + memcpy(txbuf, (const void *)SM2OutPri_CMD, sizeof(SM2OutPri_CMD)); + + SendCMD(txbuf, rxbuf); + + RcvINS(txbuf, rxbuf, txbuf[1]); // 指令 + + RcvLEN(txbuf, rxbuf + 1, 1); //长度 多加一个字节的 CRC + + RcvData(txbuf, rxbuf + 2); + + RcvSW(txbuf, rxbuf + 2 + rxbuf[1], 0x90); + + //计算接收到数据的CRC + if (CalcCRC7(rxbuf + 2, rxbuf[1] - 1) != rxbuf[rxbuf[1] + 1]) + { + //CRC Error 命令重发,超过3次,结束 + if (cnt < 3) + { + cnt++; + goto CMD_RESEND; + printf("cnt over\n"); + } + else + { + printf("ERROR\n"); + } + } + + //printf("rx %1d bytes: ", rxbuf[1]+4); +#ifdef __ANDROID__ + __android_log_print(ANDROID_LOG_INFO, TAG_SPI, "rx %1d bytes:", rxbuf[1] + 4); +#endif + + memcpy(result, rxbuf + 2, rxbuf[1]-1); + * len = rxbuf[1]-1; + return 0; +} + +int NrsecPort::SM2ImportPublicKey(int index, const uint8_t new_key[])//外部公钥导入存放在01 +{ + int i; + int cnt; + uint8_t txbuf[256]; + uint8_t rxbuf[256]; + + int retval; + int msglen; + + msglen = 5; + memset(rxbuf, 0, sizeof(rxbuf)); + memset(txbuf, 0, sizeof(txbuf)); + + SM2InPub_CMD[3] = index; + + //printf("tx %1d bytes: ", msglen); + //__android_log_print(ANDROID_LOG_INFO, "SPi", "tx %1d bytes", msglen); + +CMD_RESEND: + + memcpy(txbuf, (const void *)SM2InPub_CMD, sizeof(SM2InPub_CMD)); + + SendCMD(txbuf, rxbuf); + + RcvINS(txbuf, rxbuf, txbuf[1]); // 指令 + + SendId(txbuf, rxbuf, 0x55); + + memcpy(txbuf, new_key, 64); + + SendData(txbuf, rxbuf, 64); + + SendEnd(txbuf, rxbuf); + + RcvSW(txbuf, rxbuf + 1, 0x90); + + std::string result = "InPub: success"; +#ifdef __ANDROID__ + __android_log_print(ANDROID_LOG_INFO, TAG_SPI, "%s", result.c_str()); +#endif + //__android_log_print(ANDROID_LOG_INFO, "SPi", "%s", rxbuf); + // printf("\n"); + + + return 0; +} + +int NrsecPort::SM2ImportPrivateKey(int index, const uint8_t new_key[])//导入私钥 没测试 +{ + int i; + int cnt; + uint8_t txbuf[256]; + uint8_t rxbuf[256]; + + int retval; + int msglen; + + msglen = 5; + memset(rxbuf, 0, sizeof(rxbuf)); + memset(txbuf, 0, sizeof(txbuf)); + + SM2InPri_CMD[3] = index; + + //printf("tx %1d bytes: ", msglen); + //__android_log_print(ANDROID_LOG_INFO, "SPi", "tx %1d bytes", msglen); + +CMD_RESEND: + + memcpy(txbuf, (const void *)SM2InPri_CMD, sizeof(SM2InPri_CMD)); + + SendCMD(txbuf, rxbuf); + + RcvINS(txbuf, rxbuf, txbuf[1]); // 指令 + + SendId(txbuf, rxbuf, 0x55); + + memcpy(txbuf, new_key, 32); + + SendData(txbuf, rxbuf, 32); + + SendEnd(txbuf, rxbuf); + + RcvSW(txbuf, rxbuf + 1, 0x90); + + std::string result = "InPri: success"; +#ifdef __ANDROID__ + __android_log_print(ANDROID_LOG_INFO, TAG_SPI, "%s", result.c_str()); +#endif + + + return 0; +} + +int NrsecPort::SM3Hash(uint8_t *to_hash, int len, uint8_t *out_hash)//原始哈希 跑通了,没有验证 +{ + int i; + int cnt; + uint8_t txbuf[512]; + uint8_t rxbuf[512]; + + int retval; + int msglen; + + msglen = 5; + memset(rxbuf, 0, sizeof(rxbuf)); + memset(txbuf, 0, sizeof(txbuf)); + + + SM3Hash_CMD[3] = len >> 8; + SM3Hash_CMD[4] = len & 0xFF; + +#ifdef __ANDROID__ + __android_log_print(ANDROID_LOG_INFO, "len", "len=%x", len); +#endif + //printf("tx %1d bytes: ", msglen); + //__android_log_print(ANDROID_LOG_INFO, "SPi", "tx %1d bytes", msglen); + +CMD_RESEND: + + memcpy(txbuf, (const void *)SM3Hash_CMD, sizeof(SM3Hash_CMD)); + + SendCMD(txbuf, rxbuf); + + RcvINS(txbuf, rxbuf, txbuf[1]); + + SendId(txbuf, rxbuf, 0x55); + + memcpy(txbuf, to_hash, len); + + SendData(txbuf, rxbuf, len); + + SendEnd(txbuf, rxbuf); + + memcpy(txbuf, (const void *)SM3Hash_CMD, sizeof(SM3Hash_CMD)); + + RcvINS(txbuf, rxbuf, txbuf[1]); + + RcvLEN(txbuf, rxbuf + 1, 1); + + RcvData(txbuf, rxbuf + 2); + + RcvSW(txbuf, rxbuf + 2 + rxbuf[1], 0x90); + + //__android_log_print(ANDROID_LOG_INFO, "SPi", "rx %1d bytes:", rxbuf[1]+4); + + memcpy(out_hash, rxbuf + 2, rxbuf[1]-1); + + return 0; +} + +int NrsecPort::SM3Hash(uint8_t *in, int inl, uint8_t *out, uint8_t *pubkey, uint8_t* pucID, int idl) +{ + int nRet, l; + uint8_t *Z = NULL; + int entl = 0; + uint8_t tmpm[32]; + uint8_t abxy[32 * 4] = { + 0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* a */ + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFC, + 0x28,0xE9,0xFA,0x9E,0x9D,0x9F,0x5E,0x34,0x4D,0x5A,/* b */ + 0x9E,0x4B,0xCF,0x65,0x09,0xA7,0xF3,0x97,0x89,0xF5, + 0x15,0xAB,0x8F,0x92,0xDD,0xBC,0xBD,0x41,0x4D,0x94, + 0x0E,0x93, + 0x32,0xC4,0xAE,0x2C,0x1F,0x19,0x81,0x19,0x5F,0x99,/* x */ + 0x04,0x46,0x6A,0x39,0xC9,0x94,0x8F,0xE3,0x0B,0xBF, + 0xF2,0x66,0x0B,0xE1,0x71,0x5A,0x45,0x89,0x33,0x4C, + 0x74,0xC7, + 0xBC,0x37,0x36,0xA2,0xF4,0xF6,0x77,0x9C,0x59,0xBD,/* y */ + 0xCE,0xE3,0x6B,0x69,0x21,0x53,0xD0,0xA9,0x87,0x7C, + 0xC6,0x2A,0x47,0x40,0x02,0xDF,0x32,0xE5,0x21,0x39, + 0xF0,0xA0 + }; + l = 2 + idl + 32 * 6; + Z = (uint8_t *)malloc(l); + if (!Z) + return -1; + entl = idl * 8; + memset(Z + 1, entl & 0xFF, 1); + entl >>= 8; + memset(Z, entl & 0xFF, 1); + memcpy(Z + 2, pucID, idl); + memcpy(Z + 2 + idl, abxy, 32 * 4); + memcpy(Z + 2 + idl + 4 * 32, pubkey, 32); + memcpy(Z + 2 + idl + 5 * 32, pubkey + 32, 32); + nRet = SM3Hash(Z, l, tmpm); + if (nRet != 0) + goto quit; + free(Z); + l = inl + 32; + Z = (uint8_t *)malloc(l); + if (!Z) { + nRet = -1; + goto quit; + } + memcpy(Z, tmpm, 32); + memcpy(Z + 32, in, inl); + nRet = SM3Hash(Z, l, out); +quit: + if (Z) + free(Z); + return nRet; +}//用于签名的处理哈希值,用户标识01*16 + +int NrsecPort::SM2Sign(int index, const uint8_t *to_sign, uint8_t *out_sign)//SM2签名 所使用的哈希值应该来源于sm3hash_tosm2 +{ + int i; + int cnt; + uint8_t txbuf[256]; + uint8_t rxbuf[256]; + + int retval; + int msglen; + + msglen = 5; + memset(rxbuf, 0, sizeof(rxbuf)); + memset(txbuf, 0, sizeof(txbuf)); + + //printf("tx %1d bytes: ", msglen); + //__android_log_print(ANDROID_LOG_INFO, "SPi", "tx %1d bytes", msglen); + SM2Sign_CMD[3] = index; + +CMD_RESEND: + + memcpy(txbuf, (const void *)SM2Sign_CMD, sizeof(SM2Sign_CMD)); + + SendCMD(txbuf, rxbuf); + + RcvINS(txbuf, rxbuf, txbuf[1]); + + SendId(txbuf, rxbuf, 0x55); + + memcpy(txbuf, to_sign, 32); + + SendData(txbuf, rxbuf, 32); + + SendEnd(txbuf, rxbuf); + + memcpy(txbuf, (const void *)SM2Sign_CMD, sizeof(SM2Sign_CMD)); + + RcvINS(txbuf, rxbuf, txbuf[1]); + + RcvLEN(txbuf, rxbuf + 1, 1); + + RcvData(txbuf, rxbuf + 2); + + RcvSW(txbuf, rxbuf + 2 + rxbuf[1], 0x90); +#ifdef __ANDROID__ + __android_log_print(ANDROID_LOG_INFO, TAG_SPI, "rx %1d bytes:", rxbuf[1] + 4); +#endif + memcpy(out_sign, rxbuf + 2, rxbuf[1]-1); + return 0; +} + +int NrsecPort::SM2VerifySign(int index, uint8_t *hash, uint8_t *vs)//SM2验签 +{ + uint8_t txbuf[256]; + uint8_t rxbuf[256]; + + int retval; + int msglen; + + msglen = 5; + memset(rxbuf, 0, sizeof(rxbuf)); + memset(txbuf, 0, sizeof(txbuf)); + + //printf("tx %1d bytes: ", msglen); + //__android_log_print(ANDROID_LOG_INFO, "SPi", "tx %1d bytes", msglen); + SM2VerifySign_CMD[3] = index; + +CMD_RESEND: + + memcpy(txbuf, (const void *)SM2VerifySign_CMD, sizeof(SM2VerifySign_CMD)); + + SendCMD(txbuf, rxbuf); + + RcvINS(txbuf, rxbuf, txbuf[1]); + + SendId(txbuf, rxbuf, 0x55); + + memcpy(txbuf, hash, 32); + memcpy(txbuf + 32, vs, 64); + + SendData(txbuf, rxbuf, 96); + + SendEnd(txbuf, rxbuf); + + RcvSW(txbuf, rxbuf, 0x90); +#ifdef __ANDROID__ + __android_log_print(ANDROID_LOG_INFO, "SPi", "rx %1d bytes:", rxbuf[1] + 4); +#endif + + return 0; +} + +int NrsecPort::SM2Encrypt(int index, uint8_t *to_encrypt, uint8_t *out_encrypt)//加密 +{ + int i; + int cnt; + uint8_t txbuf[512]; + uint8_t rxbuf[512]; + + int retval; + int msglen; + + msglen = 5; + memset(rxbuf, 0, sizeof(rxbuf)); + memset(txbuf, 0, sizeof(txbuf)); + + //printf("tx %1d bytes: ", msglen); + //__android_log_print(ANDROID_LOG_INFO, "SPi", "tx %1d bytes", msglen); + SM2encrypt_CMD[3] = index; + +CMD_RESEND: + + memcpy(txbuf, (const void *)SM2encrypt_CMD, sizeof(SM2encrypt_CMD)); + + SendCMD(txbuf, rxbuf); + + RcvINS(txbuf, rxbuf, txbuf[1]); + + SendId(txbuf, rxbuf, 0x55); + + memcpy(txbuf, to_encrypt, 32); + + SendData(txbuf, rxbuf, 32); + + SendEnd(txbuf, rxbuf); + + memcpy(txbuf, (const void *)SM2encrypt_CMD, sizeof(SM2encrypt_CMD)); + + RcvINS(txbuf, rxbuf, txbuf[1]); + + RcvLEN(txbuf, rxbuf + 1, 1); + + RcvData(txbuf, rxbuf + 2); + + RcvSW(txbuf, rxbuf + 2 + rxbuf[1], 0x90); + + //__android_log_print(ANDROID_LOG_INFO, "SPi", "rx %1d bytes:", rxbuf[1]+4); + memcpy(out_encrypt, rxbuf + 2, rxbuf[1]-1); + + return 0; +} +int NrsecPort::SM2Decrypt(int index, uint8_t *to_decoder, uint8_t *out_decoder)//解密 +{ + int i; + int cnt; + uint8_t txbuf[512]; + uint8_t rxbuf[512]; + + int retval; + int msglen; + + msglen = 5; + memset(rxbuf, 0, sizeof(rxbuf)); + memset(txbuf, 0, sizeof(txbuf)); + + //printf("tx %1d bytes: ", msglen); + //__android_log_print(ANDROID_LOG_INFO, "SPi", "tx %1d bytes", msglen); + SM2decoder_CMD[3] = index; + +CMD_RESEND: + + memcpy(txbuf, (const void *)SM2decoder_CMD, sizeof(SM2decoder_CMD)); + + SendCMD(txbuf, rxbuf); + + RcvINS(txbuf, rxbuf, txbuf[1]); + + SendId(txbuf, rxbuf, 0x55); + + memcpy(txbuf, to_decoder, 128); + + SendData(txbuf, rxbuf, 128); + + SendEnd(txbuf, rxbuf); + + memcpy(txbuf, (const void *)SM2decoder_CMD, sizeof(SM2decoder_CMD)); + + RcvINS(txbuf, rxbuf, txbuf[1]); + + RcvLEN(txbuf, rxbuf + 1, 1); + + RcvData(txbuf, rxbuf + 2); + + RcvSW(txbuf, rxbuf + 2 + rxbuf[1], 0x90); + + //__android_log_print(ANDROID_LOG_INFO, "SPi", "rx %1d bytes:", rxbuf[1]+4); + memcpy(out_decoder, rxbuf + 2, rxbuf[1]-1); + + return 0; +} + +int NrsecPort::SM2cert(int type, int index, string cert, uint8_t *out_cert, uint16_t *len)//证书 +{ + int i; + int cnt; + uint8_t txbuf[512]; + uint8_t rxbuf[1024]; + + int retval; + int msglen; + + msglen = 5; + memset(rxbuf, 0, sizeof(rxbuf)); + memset(txbuf, 0, sizeof(txbuf)); + + //printf("tx %1d bytes: ", msglen); + + int certlen = cert.length(); + + SM2cert_CMD[2] = type; + SM2cert_CMD[3] = index; + SM2cert_CMD[4] = certlen; + +CMD_RESEND: + + memcpy(txbuf, (const void *)SM2cert_CMD, sizeof(SM2cert_CMD)); + + SendCMD(txbuf, rxbuf); + + RcvINS(txbuf, rxbuf, txbuf[1]); + + SendId(txbuf, rxbuf, 0x55); + + memcpy(txbuf, cert.c_str(), certlen); + + SendData(txbuf, rxbuf, certlen); + + SendEnd(txbuf, rxbuf); + + memcpy(txbuf, (const void *)SM2cert_CMD, sizeof(SM2cert_CMD)); + + RcvINS(txbuf, rxbuf, txbuf[1]); + + RcvLEN(txbuf, rxbuf + 1, 2); + + uint16_t outlen =(*(rxbuf+1)<<8)+(*(rxbuf+2)); + + RcvData(txbuf, rxbuf + 3, outlen); + + RcvSW(txbuf, rxbuf + 3 + outlen, 0x90); + + //__android_log_print(ANDROID_LOG_INFO, "SPi", "rx %1d bytes:", rxbuf[1]+4); + + memcpy(out_cert, rxbuf + 3, outlen-1); + + *len =outlen -1; + + return 0; +} +int NrsecPort::Indentify(uint8_t *to_idt, uint8_t *out_idt)//安全认证 +{ + int i; + int cnt; + uint8_t txbuf[512]; + uint8_t rxbuf[512]; + + int retval; + int msglen; + + msglen = 5; + memset(rxbuf, 0, sizeof(rxbuf)); + memset(txbuf, 0, sizeof(txbuf)); + + //printf("tx %1d bytes: ", msglen); + //__android_log_print(ANDROID_LOG_INFO, "SPi", "tx %1d bytes", msglen); + +CMD_RESEND: + + memcpy(txbuf, (const void *)Indentify_CMD, sizeof(Indentify_CMD)); + + SendCMD(txbuf, rxbuf); + + RcvINS(txbuf, rxbuf, txbuf[1]); + + SendId(txbuf, rxbuf, 0x55); + + memcpy(txbuf, to_idt, 32); + + SendData(txbuf, rxbuf, 32); + + SendEnd(txbuf, rxbuf); + + memcpy(txbuf, (const void *)SM2decoder_CMD, sizeof(SM2decoder_CMD)); + + RcvINS(txbuf, rxbuf, txbuf[1]); + + RcvLEN(txbuf, rxbuf + 1, 1); + + RcvData(txbuf, rxbuf + 2); + + RcvSW(txbuf, rxbuf + 2 + rxbuf[1], 0x90); + + //__android_log_print(ANDROID_LOG_INFO, "SPi", "rx %1d bytes:", rxbuf[1]+4); + memcpy(out_idt, rxbuf + 2, rxbuf[1]-1); + + return 0; +} diff --git a/app/src/main/cpp/NrsecPort.h b/app/src/main/cpp/NrsecPort.h new file mode 100644 index 0000000..0d7b6cd --- /dev/null +++ b/app/src/main/cpp/NrsecPort.h @@ -0,0 +1,58 @@ +#ifndef __NRSECPORT_H__ +#define __NRSECPORT_H__ + +#include "SpiPort.h" +#include + + +#define CMD_HEAD_SIZE 5 +using namespace std; +typedef uint8_t uint8_t; + +class NrsecPort : public SpiPort { +public: + + int SM1ImportKey(const uint8_t* ek, const uint8_t* ak); + int ImportIV(const uint8_t* iv, uint8_t ivLength); + + int SM1Encrypt(const uint8_t* data, uint16_t dataLen, uint8_t* encryptedData, uint16_t *bufferLen); + int SM1Decrypt(const uint8_t* encryptedData, uint16_t encryptedDataLen, uint8_t* data, uint16_t* bufferLen); + + int Random(uint8_t* output, uint8_t length); + std::string Version(); + int Indentify(uint8_t *to_idt, uint8_t *out_idt); + int SM2keypair(int index); + int SM2ExportPublicKey(int index, uint8_t result[] ,uint8_t * len); + int SM2ExportPrivateKey(int index, uint8_t result[] ,uint8_t * len); + int SM2ImportPublicKey(int index, const uint8_t new_key[]); + int SM2ImportPrivateKey(int index, const uint8_t new_key[]); + int SM3Hash(uint8_t *to_hash, int len, uint8_t *out_hash); + int SM3Hash(uint8_t *in, int inl, uint8_t *out, uint8_t *pubkey, uint8_t *pucID, int idl); + int SM2Sign(int index, const uint8_t *to_sign, uint8_t *out_sign); + int SM2VerifySign(int index, uint8_t *hash, uint8_t * vs); + int SM2Encrypt(int index, uint8_t *to_encrypt, uint8_t * out_encrypt); + int SM2Decrypt(int index, uint8_t *to_decoder, uint8_t *out_decoder); + int SM2cert(int type, int index, string cert, uint8_t *out_cert, uint16_t *len); + +protected: + + uint8_t CalcCRC7(const uint8_t *buff, int len); + void SendCMD(uint8_t *cmd, uint8_t *rxbuf); + void RcvINS(uint8_t *txbuf, uint8_t *buf, uint8_t ins); + void RcvLEN(uint8_t *txbuf, uint8_t *buf, uint8_t len); + void RcvData(uint8_t *txbuf, uint8_t *buf); + void RcvData(uint8_t *txbuf, uint8_t *buf, int len); + void RcvSW(uint8_t *txbuf, uint8_t *buf, uint8_t sw); + void SendEnd(uint8_t *txbuf, uint8_t *buf); + void SendId(uint8_t *txbuf, uint8_t *buf, uint8_t id); + void SendData(uint8_t *data, uint8_t *rxbuf, int data_size); + +protected: + std::mutex m_mutex; + +}; + + + + +#endif // __NRSECPORT_H__ diff --git a/app/src/main/cpp/SpiPort.cpp b/app/src/main/cpp/SpiPort.cpp new file mode 100644 index 0000000..5cb529e --- /dev/null +++ b/app/src/main/cpp/SpiPort.cpp @@ -0,0 +1,207 @@ +#include "SpiPort.h" +#ifdef _WIN32 +#include +#include +#endif +#include +#include +#include +#include +#include +#ifdef __ANDROID__ +#include +#include +#include +#include + +#include +#include + +#include +#endif + +//typedef unsigned char u8; + +#define RE_SUC 0x01 +#define RE_ERROR 0x00 + +#define TAG_SPI "SPI" + +SpiPort::SpiPort() +#ifdef _WIN32 +#ifdef TERMINAL_SERVER + : m_fd(INVALID_HANDLE_VALUE) +#endif +#else + : m_fd(0) +#endif +{ +} + +SpiPort::~SpiPort() +{ + Close(); +} + +bool SpiPort::Open(const char *path) +{ + m_path = path; +#ifdef _WIN32 +#ifdef TERMINAL_SERVER + CW2T utf8Path(CA2W(path, CP_UTF8)); + // m_fd = _open(path, O_RDWR); + m_fd = CreateFile(utf8Path, //port name + GENERIC_READ | GENERIC_WRITE, //Read/Write + 0, // No Sharing + NULL, // No Security + OPEN_EXISTING,// Open existing port only + 0, // Non Overlapped I/O + NULL); // Null for Comm Devices + if (m_fd == INVALID_HANDLE_VALUE) + { + return false; + } +#endif + return false; +#else + m_fd = open(path, O_RDWR); + + if (m_fd < 0) { + perror("open"); + return false; + } +#endif + spi_master_init(); + + return true; +} + +void SpiPort::Close() +{ +#ifdef _WIN32 +#ifdef TERMINAL_SERVER + if (m_fd != INVALID_HANDLE_VALUE) + { + CloseHandle(m_fd); + m_fd = INVALID_HANDLE_VALUE; + } +#endif +#else + if (m_fd > 0) + { + close(m_fd); + m_fd = 0; + } +#endif +} + +bool SpiPort::IsOpened() const +{ +#ifdef _WIN32 +#ifdef TERMINAL_SERVER + return m_fd != INVALID_HANDLE_VALUE; +#else + return false; +#endif +#else + return m_fd > 0; +#endif +} + +int SpiPort::spi_transfer(uint8_t *txbuf, uint8_t *rxbuf, int bytes) +{ + int status = 0; + +#ifdef _WIN32 + + // BOOL res = DeviceIoControl(); + // status = res ? 0 : -1; +#else + +#if 0 + struct spi_ioc_transfer xfer[2]; + memset(xfer, 0, sizeof(xfer)); + xfer[0].tx_buf = (__u64)txbuf; + xfer[0].rx_buf = (__u64)rxbuf; + xfer[0].len = bytes; + xfer[0].delay_usecs = 2; + + status = ioctl(m_fd, SPI_IOC_MESSAGE(1), xfer); +#else + struct spi_ioc_transfer xfer; + memset(&xfer, 0, sizeof(xfer)); + xfer.tx_buf = (__u64)txbuf; + xfer.rx_buf = (__u64)rxbuf; + xfer.len = bytes; + xfer.delay_usecs = 2; + + status = ioctl(m_fd, SPI_IOC_MESSAGE(1), &xfer); +#endif + if (status < 0) + { + perror("SPI_IOC_MESSAGE"); + return -1; + } +#endif + + return status; +} + +void SpiPort::spi_master_init() +{ + uint8_t mode = 3; + uint8_t lsb = 0; + uint8_t bits = 8; + //uint32_t speed = 30000000; + uint32_t speed = 2000000; + //uint32_t speed = 2000000; + //uint32_t speed = 33000000; + + // SPI_IOC_WR_MODE + int res = 0; + +#ifdef __ANDROID__ + res = ioctl(m_fd, SPI_IOC_WR_MODE, &mode); + res = ioctl(m_fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); + res = ioctl(m_fd, SPI_IOC_WR_LSB_FIRST, &lsb); + + if (ioctl(m_fd, SPI_IOC_RD_MODE, &mode) < 0) + { + perror("SPI rd_mode"); + return; + } + + if (ioctl(m_fd, SPI_IOC_RD_LSB_FIRST, &lsb) < 0) + { + perror("SPI rd_lsb_fist"); + return; + } + + if (ioctl(m_fd, SPI_IOC_RD_BITS_PER_WORD, &bits) < 0) + { + perror("SPI rd bits_per_word"); + return; + } + + if (ioctl(m_fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed) < 0) + { + perror("SPI rd max_speed_hz"); + return; + } + + __android_log_print(ANDROID_LOG_INFO, TAG_SPI, "%s: spi mode %d, %d bits %sper word, %d Hz max\n", m_path.c_str(), mode, bits, lsb ? "(lsb first) " : "", speed); +#endif + + //printf("%s: spi mode %d, %d bits %sper word, %d Hz max\n", + // name, mode, bits, lsb ? "(lsb first) " : "", speed); +} + +int SpiPort::delay(int x) +{ +#ifdef _WIN32 + std::this_thread::sleep_for(std::chrono::milliseconds(x)); +#else + usleep(x); +#endif + return 0; +} diff --git a/app/src/main/cpp/SpiPort.h b/app/src/main/cpp/SpiPort.h new file mode 100644 index 0000000..a04f6d5 --- /dev/null +++ b/app/src/main/cpp/SpiPort.h @@ -0,0 +1,44 @@ +#ifndef TESTCOMM_SPIPORT_H +#define TESTCOMM_SPIPORT_H + +#ifdef _WIN32 +#ifdef TERMINAL_SERVER +#include +#include +#endif +#else +#include +#endif +#include +using namespace std; + +class SpiPort { +public: + + SpiPort(); + virtual ~SpiPort(); + + bool Open(const char* path); + void Close(); + bool IsOpened() const; + + int spi_transfer(uint8_t *txbuf, uint8_t *rxbuf, int bytes); + void spi_master_init(); + static int delay(int x); + +protected: + std::string m_path; + +#ifdef _WIN32 +#ifdef TERMINAL_SERVER + HANDLE m_fd; +#endif +#else + int m_fd; +#endif +}; + + + + +#endif //TESTCOMM_SPIPORT_H diff --git a/app/src/main/cpp/native-lib.cpp b/app/src/main/cpp/native-lib.cpp new file mode 100644 index 0000000..14bc1c2 --- /dev/null +++ b/app/src/main/cpp/native-lib.cpp @@ -0,0 +1,603 @@ +#include +#include +#include +#include +#include +#include +#include +#include +// #include +#include + +#include + +#define NRSEC_PATH "/dev/spidev0.0" + +#ifdef USING_BREAK_PAD +#include "client/linux/handler/exception_handler.h" +#include "client/linux/handler/minidump_descriptor.h" +#endif + +#include +#include + +#ifdef USING_BREAK_PAD +bool DumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, + void* context, + bool succeeded) { + + LOGE("Dump path: %s\n", descriptor.path()); + return succeeded; +} +#endif + +#ifdef USING_NRSEC +#include "NrsecPort.h" +#endif + + +std::string MakeString(const char* sz) +{ + return (sz == NULL) ? std::string("") : std::string(sz); +} + +void posix_signal_handler(int sig, siginfo_t *siginfo, void *context) +{ + (void)context; + switch(sig) + { + case SIGSEGV: + fputs("Caught SIGSEGV: Segmentation Fault\n", stderr); + break; + case SIGINT: + fputs("Caught SIGINT: Interactive attention signal, (usually ctrl+c)\n", + stderr); + break; + case SIGFPE: + switch(siginfo->si_code) + { + case FPE_INTDIV: + fputs("Caught SIGFPE: (integer divide by zero)\n", stderr); + break; + case FPE_INTOVF: + fputs("Caught SIGFPE: (integer overflow)\n", stderr); + break; + case FPE_FLTDIV: + fputs("Caught SIGFPE: (floating-point divide by zero)\n", stderr); + break; + case FPE_FLTOVF: + fputs("Caught SIGFPE: (floating-point overflow)\n", stderr); + break; + case FPE_FLTUND: + fputs("Caught SIGFPE: (floating-point underflow)\n", stderr); + break; + case FPE_FLTRES: + fputs("Caught SIGFPE: (floating-point inexact result)\n", stderr); + break; + case FPE_FLTINV: + fputs("Caught SIGFPE: (floating-point invalid operation)\n", stderr); + break; + case FPE_FLTSUB: + fputs("Caught SIGFPE: (subscript out of range)\n", stderr); + break; + default: + fputs("Caught SIGFPE: Arithmetic Exception\n", stderr); + break; + } + case SIGILL: + switch(siginfo->si_code) + { + case ILL_ILLOPC: + fputs("Caught SIGILL: (illegal opcode)\n", stderr); + break; + case ILL_ILLOPN: + fputs("Caught SIGILL: (illegal operand)\n", stderr); + break; + case ILL_ILLADR: + fputs("Caught SIGILL: (illegal addressing mode)\n", stderr); + break; + case ILL_ILLTRP: + fputs("Caught SIGILL: (illegal trap)\n", stderr); + break; + case ILL_PRVOPC: + fputs("Caught SIGILL: (privileged opcode)\n", stderr); + break; + case ILL_PRVREG: + fputs("Caught SIGILL: (privileged register)\n", stderr); + break; + case ILL_COPROC: + fputs("Caught SIGILL: (coprocessor error)\n", stderr); + break; + case ILL_BADSTK: + fputs("Caught SIGILL: (internal stack error)\n", stderr); + break; + default: + fputs("Caught SIGILL: Illegal Instruction\n", stderr); + break; + } + break; + case SIGTERM: + fputs("Caught SIGTERM: a termination request was sent to the program\n", + stderr); + break; + case SIGABRT: + fputs("Caught SIGABRT: usually caused by an abort() or assert()\n", stderr); + break; + default: + break; + } + + _Exit(1); +} + +jint JNI_OnLoad(JavaVM* vm, void* reserved) +{ + JNIEnv* env = NULL; + jint result = -1; + +#if defined(JNI_VERSION_1_6) + if (result==-1 && vm->GetEnv((void**)&env, JNI_VERSION_1_6) == JNI_OK) + { + result = JNI_VERSION_1_6; + } +#endif +#if defined(JNI_VERSION_1_4) + if (result==-1 && vm->GetEnv((void**)&env, JNI_VERSION_1_4) == JNI_OK) + { + result = JNI_VERSION_1_4; + } +#endif +#if defined(JNI_VERSION_1_2) + if (result==-1 && vm->GetEnv((void**)&env, JNI_VERSION_1_2) == JNI_OK) + { + result = JNI_VERSION_1_2; + } +#endif + + if(result == -1 || env == NULL) + { + return JNI_FALSE; + } + +#ifdef USING_BREAK_PAD + google_breakpad::MinidumpDescriptor descriptor("/sdcard/Android/data/com.xypower.mpapp/files/logs/"); + google_breakpad::ExceptionHandler eh(descriptor, NULL, DumpCallback, NULL, true, -1); +#endif + + + { + struct sigaction sig_action = {}; + sig_action.sa_sigaction = posix_signal_handler; + sigemptyset(&sig_action.sa_mask); + +#ifdef __APPLE__ + /* for some reason we backtrace() doesn't work on osx + when we use an alternate stack */ + sig_action.sa_flags = SA_SIGINFO; +#else + sig_action.sa_flags = SA_SIGINFO | SA_ONSTACK; +#endif + + if (sigaction(SIGSEGV, &sig_action, NULL) != 0) { + // err(1, "sigaction"); + int aa = 0; + } + } + + + return result; +} + +bool GetJniEnv(JavaVM *vm, JNIEnv **env, bool& didAttachThread) +{ + didAttachThread = false; + *env = nullptr; + // Check if the current thread is attached to the VM + auto get_env_result = vm->GetEnv((void**)env, JNI_VERSION_1_6); + if (get_env_result == JNI_EDETACHED) + { + get_env_result = vm->AttachCurrentThread(env, NULL); + if (get_env_result == JNI_OK) { + didAttachThread = true; + } else { + // Failed to attach thread. Throw an exception if you want to. + } + } else if (get_env_result == JNI_EVERSION) + { + // Unsupported JNI version. Throw an exception if you want to. + } + + return get_env_result == JNI_OK; +} + + +bool readFile(const std::string& path, std::vector& data) +{ +#ifdef _WIN32 + CA2W pszW(path.c_str(), CP_UTF8); + std::ifstream ifs(pszW, std::ios::in | std::ios::binary | std::ios::ate); +#else + std::ifstream ifs(path, std::ios::in | std::ios::binary | std::ios::ate); +#endif + + if (ifs.is_open()) + { + std::streampos size = ifs.tellg(); + if ((long long)size > 0) + { + std::vector buffer; + data.resize(size); + + ifs.seekg(0, std::ios::beg); + ifs.read((char *)(&data[0]), size); + } + else + { + data.clear(); + } + ifs.close(); + + return true; + } + + return false; +} + +bool writeFile(const std::string& path, const unsigned char* data, size_t dataLength) +{ +#ifdef _WIN32 + CW2T pszT(CA2W(path.c_str(), CP_UTF8)); + + HANDLE hFile = CreateFile(pszT, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) + { + return false; + } + + DWORD dwBytesToWrite = static_cast(dataLength); + DWORD dwBytesWritten = 0; + BOOL bErrorFlag = WriteFile(hFile, data, dwBytesToWrite, &dwBytesWritten, NULL); + + ::CloseHandle(hFile); + return (TRUE == bErrorFlag); +#else + + FILE* fp = fopen(path.c_str(), "wb"); + if (fp != NULL) + { + fwrite(data, 1, dataLength, fp); + fclose(fp); + return true; + } + /* std::ofstream ofs; + ofs.open(path, std::ios::out | std::ios::binary | std::ios::trunc); + if (ofs.is_open()) + { + ofs.write(reinterpret_cast(data), dataLength); + ofs.close(); + return true; + } + */ + + return false; +#endif +} + + +extern "C" JNIEXPORT void JNICALL +Java_com_xypower_secapp_MicroPhotoService_setOtgState( + JNIEnv* env, + jclass cls, jboolean enabled) { + + // GpioControl::setOtgState(enabled != JNI_FALSE); + +} + +extern "C" JNIEXPORT void JNICALL +Java_com_xypower_secapp_MicroPhotoService_setCam3V3Enable( + JNIEnv* env, + jclass cls, jboolean enabled) { + + // GpioControl::setCam3V3Enable(enabled != JNI_FALSE); +} + +extern "C" JNIEXPORT jstring JNICALL +Java_com_xypower_secapp_MicroPhotoService_getSerialNumber( + JNIEnv* env, + jclass cls) { + + char value[PROP_VALUE_MAX] = { 0 }; + __system_property_get("ro.serialno", value); + return env->NewStringUTF(value); +} + + +extern "C" JNIEXPORT jboolean JNICALL +Java_com_xypower_secapp_MicroPhotoService_importPublicKeyFile( + JNIEnv* env, jclass cls, jint index, jstring outputPath, jstring md5) { + +#ifdef USING_NRSEC + + // NrsecSpiPort spi("/dev/mtkgpioctrl"); + // NrsecSpiPort spi("/dev/spidevSE"); + // const char *port = "/dev/mtkgpioctrl"; + + if (env->GetStringUTFLength(outputPath) <=0) + { + return JNI_FALSE; + } + + NrsecPort nrsec; + const char *path = NRSEC_PATH; + if (!nrsec.Open(path)) + { + return JNI_FALSE; + } + + const char *outputPathStr = env->GetStringUTFChars(outputPath, 0); + const char *md5Str = env->GetStringUTFChars(md5, 0); + + bool res = false; + std::vector data; + if (readFile(outputPathStr, data) && !data.empty()) + { + res = nrsec.SM2ImportPublicKey(index, &data[0]) == 0; + } + + nrsec.Close(); + + env->ReleaseStringUTFChars(outputPath, outputPathStr); + env->ReleaseStringUTFChars(md5, md5Str); + + return res ? JNI_TRUE : JNI_FALSE; +#endif +} + +extern "C" JNIEXPORT jboolean JNICALL +Java_com_xypower_secapp_MicroPhotoService_importPublicKey( + JNIEnv* env, jclass cls, jint index, jbyteArray cert) { + +#ifdef USING_NRSEC + + int byteCertLen = env->GetArrayLength(cert); + if (byteCertLen <= 0) + { + return JNI_FALSE; + } + + NrsecPort nrsec; + const char *path = NRSEC_PATH; + if (!nrsec.Open(path)) + { + return JNI_FALSE; + } + + jbyte* byteCert = env->GetByteArrayElements(cert, 0); + + bool res = nrsec.SM2ImportPublicKey(index, (const uint8_t*)byteCert) == 0; + + nrsec.Close(); + + env->ReleaseByteArrayElements(cert, byteCert, JNI_ABORT); + + return res ? JNI_TRUE : JNI_FALSE; +#endif +} + +extern "C" JNIEXPORT jboolean JNICALL +Java_com_xypower_secapp_MicroPhotoService_genKeys( + JNIEnv* env, + jclass cls, jint index) { + +#ifdef USING_NRSEC + // GpioControl::setRS485Enable(true); + + //GpioControl::setSpiMode(SPI_MODE_3); + //GpioControl::setSpiBitsPerWord(8); + //GpioControl::setSpiMaxSpeedHz(33000000); + + const char *path = NRSEC_PATH; + + NrsecPort nrsec; + if (!nrsec.Open(path)) + { + return JNI_FALSE; + } + + bool res = nrsec.SM2keypair(index) == 0; + + nrsec.Close(); + + return res ? JNI_TRUE : JNI_FALSE; +#endif + +} + +extern "C" JNIEXPORT jstring JNICALL +Java_com_xypower_secapp_MicroPhotoService_querySecVersion( + JNIEnv* env, + jclass cls) { +#ifdef USING_NRSEC + + const char *path = NRSEC_PATH; + + NrsecPort nrsec; + if (!nrsec.Open(path)) + { + return NULL; + } + + std::string version = nrsec.Version(); + nrsec.Close(); + + return env->NewStringUTF(version.c_str()); +#endif +} + +extern "C" JNIEXPORT jboolean JNICALL +Java_com_xypower_secapp_MicroPhotoService_genCertRequest( + JNIEnv* env, jclass cls, jint index, jint type, jstring subject, jstring outputPath) { + +#ifdef USING_NRSEC + if (env->GetStringUTFLength(subject) <=0 || env->GetStringUTFLength(outputPath) <=0) + { + return JNI_FALSE; + } + const char *path = NRSEC_PATH; + + NrsecPort nrsec; + if (!nrsec.Open(path)) + { + return JNI_FALSE; + } + + uint8_t output[1024] = { 0 }; + uint16_t len = 0; + const char* subjectStr = env->GetStringUTFChars(subject, 0); + + bool res = nrsec.SM2cert(type, index, MakeString(subjectStr), output, &len) == 0; + nrsec.Close(); + env->ReleaseStringUTFChars(subject, subjectStr); + if (!res) + { + return JNI_FALSE; + } + + const char* outputPathStr = env->GetStringUTFChars(outputPath, 0); + FILE* file = fopen(outputPathStr, "wb"); + env->ReleaseStringUTFChars(outputPath, outputPathStr); + if (file == NULL) + { + return JNI_FALSE; + } + + int bytes = fwrite(output, sizeof(unsigned char), len, file); + fclose(file); + + return bytes == len ? JNI_TRUE : JNI_FALSE; +#endif +} + +extern "C" JNIEXPORT jboolean JNICALL +Java_com_xypower_secapp_MicroPhotoService_importPrivateKeyFile( + JNIEnv* env, jclass cls, jint index, jstring outputPath, jstring md5) { + +#ifdef USING_NRSEC + + if (env->GetStringUTFLength(outputPath)<=0) + { + return JNI_FALSE; + } + const char *path = NRSEC_PATH; + + NrsecPort nrsec; + if (!nrsec.Open(path)) + { + return JNI_FALSE; + } + + const char *outputPathStr = env->GetStringUTFChars(outputPath, 0); + const char *md5Str = env->GetStringUTFChars(md5, 0); + + bool res = false; + std::vector data; + if (readFile(outputPathStr, data) && !data.empty()) + { + res = nrsec.SM2ImportPrivateKey(index, &data[0]) == 0; + } + + nrsec.Close(); + + env->ReleaseStringUTFChars(outputPath, outputPathStr); + env->ReleaseStringUTFChars(md5, md5Str); + + return res ? JNI_TRUE : JNI_FALSE; + +#endif +} + +extern "C" JNIEXPORT jboolean JNICALL +Java_com_xypower_secapp_MicroPhotoService_exportPublicKeyFile( + JNIEnv* env, jclass cls, jint index, jstring outputPath) { + +#ifdef USING_NRSEC + + if (env->GetStringUTFLength(outputPath) <= 0) + { + return JNI_FALSE; + } + + const char *path = NRSEC_PATH; + NrsecPort nrsec; + if (!nrsec.Open(path)) + { + return JNI_FALSE; + } + + bool res = false; + std::vector data(64, 0); + uint8_t len = 0; + res = nrsec.SM2ExportPublicKey(index, &data[0], &len) == 0; + nrsec.Close(); + if (!res) + { + return JNI_FALSE; + } + + const char* outputPathStr = env->GetStringUTFChars(outputPath, 0); + FILE* file = fopen(outputPathStr, "wb"); + env->ReleaseStringUTFChars(outputPath, outputPathStr); + if (file == NULL) + { + return JNI_FALSE; + } + + int bytes = fwrite(&data[0], sizeof(unsigned char), len, file); + + fclose(file); + return bytes == len ? JNI_TRUE : JNI_FALSE; +#endif +} + +extern "C" JNIEXPORT jboolean JNICALL +Java_com_xypower_secapp_MicroPhotoService_exportPrivateFile( + JNIEnv* env, jclass cls, jint index, jstring outputPath) { + +#ifdef USING_NRSEC + + if (env->GetStringUTFLength(outputPath)<=0) + { + return JNI_FALSE; + } + + const char *path = NRSEC_PATH; + NrsecPort nrsec; + if (!nrsec.Open(path)) + { + return JNI_FALSE; + } + + bool res = false; + std::vector data(64,0); + uint8_t len = 0; + res = nrsec.SM2ExportPrivateKey(index, &data[0], &len) == 0; + nrsec.Close(); + if (!res) + { + return JNI_FALSE; + } + + const char* outputPathStr = env->GetStringUTFChars(outputPath, 0); + FILE* file = fopen(outputPathStr, "wb"); + env->ReleaseStringUTFChars(outputPath, outputPathStr); + if (file == NULL) + { + return JNI_FALSE; + } + + int bytes = fwrite(&data[0], sizeof(unsigned char), len, file); + + fclose(file); + return bytes == len ? JNI_TRUE : JNI_FALSE; +#endif +} diff --git a/app/src/main/java/com/xypower/secapp/CertActivity.java b/app/src/main/java/com/xypower/secapp/CertActivity.java new file mode 100644 index 0000000..88e7121 --- /dev/null +++ b/app/src/main/java/com/xypower/secapp/CertActivity.java @@ -0,0 +1,243 @@ +package com.xypower.secapp; + + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.support.v7.app.ActionBar; +import android.support.v7.app.AppCompatActivity; +import android.text.TextUtils; +import android.util.Base64; +import android.util.Log; +import android.view.View; +import android.widget.TextView; + +import com.dowse.devicesdk.DsDeviceSdk; + +import java.io.File; +import java.text.SimpleDateFormat; +import java.util.Date; + +public class CertActivity extends AppCompatActivity { + + private static String TAG = "CERTTAG"; + private final static String ACTION_IMP_PUBKEY = "imp_pubkey"; + private final static String ACTION_EXP_PUBKEY = "exp_pubkey"; + private final static String ACTION_EXP_PRIKEY = "exp_prikey"; + private final static String ACTION_GEN_KEYS = "gen_keys"; + private final static String ACTION_CERT_REQ = "cert_req"; + + private static long AUTO_CLOSE_TIMEOUT = 200; + + private Handler mHandler = null; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_cert); + + int res = 0; + + DsDeviceSdk dsSdk = DsDeviceSdk.getInstance(); + dsSdk.init(); + + res = dsSdk.mcuInit(); + res = dsSdk.mcuOpen(); + + boolean bres = dsSdk.mcuPowerOnCPR(); + // String v = dsSdk.nrsecGetVersion(); + + // res = dsSdk.nrsecInit(); + // res = dsSdk.nrsecOpen(); + + String version = MicroPhotoService.querySecVersion(); + + TextView textView = (TextView)findViewById(R.id.textView); + textView.setText(R.string.nrsec_version + version); + + ActionBar actionBar = getSupportActionBar(); + String text = getResources().getString(R.string.nrsec_version); + actionBar.setTitle(actionBar.getTitle().toString() + " " + text + " " + version); + + + SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + Date dt = new Date(); + text = format.format(dt); + + ((TextView) findViewById(R.id.textView)).setText(text); + + mHandler = new Handler(); + + { + Intent intent = getIntent(); + if (intent != null) { + handleCommand(intent); + } + } + + findViewById(R.id.btnGenKeys).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(); + intent.putExtra("index", 1); + intent.putExtra("action", ACTION_GEN_KEYS); + handleCommand(intent); + } + }); + + findViewById(R.id.btnExpPriKey).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(); + intent.putExtra("index", 1); + intent.putExtra("action", ACTION_EXP_PRIKEY); + + intent.putExtra("path", "/data/data/com.xypower.secapp/data/pri.key"); + + handleCommand(intent); + } + }); + + findViewById(R.id.btnExpPubKey).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(); + intent.putExtra("index", 1); + intent.putExtra("action", ACTION_EXP_PUBKEY); + + File file = CertActivity.this.getFilesDir(); + String absPath = file.getAbsolutePath(); + intent.putExtra("path", "/data/data/com.xypower.secapp/data/pub.key"); + + handleCommand(intent); + } + }); + + findViewById(R.id.btnGenCertReq).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(); + intent.putExtra("index", 1); + intent.putExtra("action", ACTION_CERT_REQ); + intent.putExtra("subject", "C=CN,ST=SH,L=SH,O=SGCC,OU=NC,CN=123456_0006_XY2024ICQ1110006"); + + File file = CertActivity.this.getFilesDir(); + String absPath = file.getAbsolutePath(); + intent.putExtra("path", "/data/data/com.xypower.secapp/data/pub.key"); + + handleCommand(intent); + } + }); + // + } + + protected void handleCommand(Intent intent) { + + final String action = intent.getStringExtra("action"); + if (!TextUtils.isEmpty(action)) { + if (TextUtils.equals(action, ACTION_IMP_PUBKEY)) { + String cert = intent.getStringExtra("cert"); + String path = intent.getStringExtra("path"); + int index = intent.getIntExtra("index", 1); + + if (!TextUtils.isEmpty(cert)) { + // Import + // String cert = intent.getStringExtra("md5"); + byte[] content = Base64.decode(cert, Base64.DEFAULT); + if (content != null) { + MicroPhotoService.importPublicKey(index, content); + } + } else if (TextUtils.isEmpty(path)) { + String md5 = intent.getStringExtra("md5"); + File file = new File(path); + if (file.exists() && file.isFile()) { + MicroPhotoService.importPublicKeyFile(index, path, md5); + } + } + } else if (TextUtils.equals(action, ACTION_GEN_KEYS)) { + int index = intent.getIntExtra("index", 0); + boolean res = MicroPhotoService.genKeys(index); + } else if (TextUtils.equals(action, ACTION_CERT_REQ)) { + int index = intent.getIntExtra("index", 0); + int type = intent.getIntExtra("type", 0); + String subject = intent.getStringExtra("subject"); + String path = intent.getStringExtra("path"); + ensureDirectoryExisted(path); + + boolean res = MicroPhotoService.genCertRequest(index, type, subject, path); + if (res) { + Log.i(TAG, "Succeeded to generate cert request"); + } else { + Log.i(TAG, "Failed to generate cert request"); + } + } else if (TextUtils.equals(action, ACTION_EXP_PUBKEY)) { + String path = intent.getStringExtra("path"); + File file = new File(path); + File parentPath = file.getParentFile(); + if (!parentPath.exists()) { + parentPath.mkdirs(); + } + int index = intent.getIntExtra("index", 1); + + boolean res = MicroPhotoService.exportPublicKeyFile(index, path); + if (res) { + Log.i(TAG, "Succeeded to export public key"); + } else { + Log.i(TAG, "Failed to export public key"); + } + } else if (TextUtils.equals(action, ACTION_EXP_PRIKEY)) { + String path = intent.getStringExtra("path"); + File file = new File(path); + File parentPath = file.getParentFile(); + if (!parentPath.exists()) { + parentPath.mkdirs(); + } + int index = intent.getIntExtra("index", 1); + + boolean res = MicroPhotoService.exportPrivateFile(index, path); + if (res) { + Log.i(TAG, "Succeeded to export private key"); + } else { + Log.i(TAG, "Failed to export private key"); + } + } + + final Activity activity = this; + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + // activity.finish(); + System.exit(0); + } + }, AUTO_CLOSE_TIMEOUT); + } + } + + protected void ensureDirectoryExisted(String fileName) { + File file = new File(fileName); + try { + File parentFile = file.getParentFile(); + if (!parentFile.exists()) { + file.getParentFile().mkdirs(); + } + } catch (Exception ex) { + + } + } + + @Override + protected void onDestroy() { + DsDeviceSdk dsSdk = DsDeviceSdk.getInstance(); + + int res = 0; + + boolean bres = dsSdk.mcuPowerOffCPR(); + res = dsSdk.mcuClose(); + res = dsSdk.mcuUnInit(); + + dsSdk.release(); + + super.onDestroy(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/xypower/secapp/MainActivity.java b/app/src/main/java/com/xypower/secapp/MainActivity.java new file mode 100644 index 0000000..048b187 --- /dev/null +++ b/app/src/main/java/com/xypower/secapp/MainActivity.java @@ -0,0 +1,28 @@ +package com.xypower.secapp; + +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.widget.TextView; +import com.xypower.secapp.databinding.ActivityMainBinding; + +public class MainActivity extends AppCompatActivity { + +private ActivityMainBinding binding; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + binding = ActivityMainBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + + + } + + /** + * A native method that is implemented by the 'myapplication' native library, + * which is packaged with this application. + */ + + +} \ No newline at end of file diff --git a/app/src/main/java/com/xypower/secapp/MicroPhotoService.java b/app/src/main/java/com/xypower/secapp/MicroPhotoService.java new file mode 100644 index 0000000..b2a7498 --- /dev/null +++ b/app/src/main/java/com/xypower/secapp/MicroPhotoService.java @@ -0,0 +1,96 @@ +package com.xypower.secapp; + +import static java.lang.System.loadLibrary; + +import android.app.AlarmManager; +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.app.Service; +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.location.Location; +import android.location.LocationListener; +import android.location.LocationManager; +import android.os.Handler; +import android.os.IBinder; +import android.os.Message; + + +public class MicroPhotoService extends Service { + public static final String TAG = "MPLOG"; + + // Used to load the 'myapplication' library on application startup. + static { + System.loadLibrary("secapp"); + } + + public static final int NOTIFICATION_ID_FOREGROUND_SERVICE = 8466503; + public static final String ACTION_MSG_BROADCAST = "ACT_MSG_BROADCAST"; + + public static final String ACTION_START = "com.xypower.mpapp.ACT_START"; + public static final String ACTION_STOP = "com.xypower.mpapp.ACT_STOP"; + public static final String ACTION_MAIN = "com.xypower.mpapp.ACT_MAIN"; + private static final String ACTION_TAKE_PHOTO = "com.xypower.mpapp.ACT_TP"; + private static final String ACTION_GPS_TIMEOUT = "com.xypower.mpapp.GPS_TIMEOUT"; + + private static final String ACTION_IMP_PUBKRY = "com.xypower.mpapp.ACT_IMP_PUBKEY"; + + private static final String ACTION_TAKE_PHOTO_MANUALLY = "com.xypower.mpapp.ACT_TP_M"; + private static final String ACTION_HEARTBEAT_MANUALLY = "com.xypower.mpapp.ACT_HB_M"; + private static final String ACTION_UPDATE_CONFIGS = "com.xypower.mpapp.ACT_UPD_CFG"; + public static final String ACTION_VIDEO_FINISHED = "com.xypower.mpapp.ACT_V_FINISHED"; + private static final String EXTRA_PARAM_CHANNEL = "Channel"; + private static final String EXTRA_PARAM_PRESET = "Preset"; + private static final String EXTRA_PARAM_PHOTO_OR_VIDEO = "PhotoOrVideo"; + private static final String EXTRA_PARAM_SCHEDULES = "Schedules"; + private static final String EXTRA_PARAM_SCHEDULE = "Schedule_"; + private static final String EXTRA_PARAM_TAKING_TIME = "TakingTime"; + private static final String EXTRA_PARAM_TIME = "Time"; + + private static final String FOREGROUND_CHANNEL_ID = "foreground_channel_id"; + public static class STATE_SERVICE { + public static final int CONNECTED = 10; + public static final int NOT_CONNECTED = 0; + } + + @Override + public IBinder onBind(Intent intent) { + // TODO: Return the communication channel to the service. + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public void onCreate() { + super.onCreate(); + } + @Override + public void onDestroy() { + super.onDestroy(); + } + + public static native void setOtgState(boolean enabled); + public static native void setCam3V3Enable(boolean enabled); + public static native String getSerialNumber(); + public static native boolean importPublicKeyFile(int index, String outputPath, String md5); + public static native boolean importPublicKey(int index, byte cert[]); + public static native boolean genKeys(int index); + + public static native String querySecVersion(); + public static native boolean genCertRequest(int index, int type, String subject, String outputPath); + public static native boolean importPrivateKeyFile(int index, String outputPath, String md5); + public static native boolean exportPublicKeyFile(int index, String outputPath); + public static native boolean exportPrivateFile(int index, String outputPath); + + + ////////////////////////GPS//////////////////// + // private static final String GPS_LOCATION_NAME = android.location.LocationManager.GPS_PROVIDER; + private LocationManager mLocationManager; + private Location mPreviousLocation = null; + private String mLocateType; + +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_cert.xml b/app/src/main/res/layout/activity_cert.xml new file mode 100644 index 0000000..19426d8 --- /dev/null +++ b/app/src/main/res/layout/activity_cert.xml @@ -0,0 +1,56 @@ + + + + + +