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 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..91bce21
--- /dev/null
+++ b/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp
new file mode 100644
index 0000000..c209e78
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.webp differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
new file mode 100644
index 0000000..b2dfe3d
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp
new file mode 100644
index 0000000..4f0f1d6
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.webp differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
new file mode 100644
index 0000000..62b611d
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
new file mode 100644
index 0000000..948a307
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
new file mode 100644
index 0000000..1b9a695
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
new file mode 100644
index 0000000..28d4b77
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
new file mode 100644
index 0000000..9287f50
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
new file mode 100644
index 0000000..aa7d642
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
new file mode 100644
index 0000000..9126ae3
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ
diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml
new file mode 100644
index 0000000..192a6d3
--- /dev/null
+++ b/app/src/main/res/values-night/themes.xml
@@ -0,0 +1,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..f8c6127
--- /dev/null
+++ b/app/src/main/res/values/colors.xml
@@ -0,0 +1,10 @@
+
+
+ #FFBB86FC
+ #FF6200EE
+ #FF3700B3
+ #FF03DAC5
+ #FF018786
+ #FF000000
+ #FFFFFFFF
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..a68034e
--- /dev/null
+++ b/app/src/main/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+ 证书处理
+ 加密芯片版本号:
+
\ No newline at end of file
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
new file mode 100644
index 0000000..94ed7f4
--- /dev/null
+++ b/app/src/main/res/values/themes.xml
@@ -0,0 +1,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/xml/backup_rules.xml b/app/src/main/res/xml/backup_rules.xml
new file mode 100644
index 0000000..fa0f996
--- /dev/null
+++ b/app/src/main/res/xml/backup_rules.xml
@@ -0,0 +1,13 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/xml/data_extraction_rules.xml b/app/src/main/res/xml/data_extraction_rules.xml
new file mode 100644
index 0000000..9ee9997
--- /dev/null
+++ b/app/src/main/res/xml/data_extraction_rules.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/test/java/com/xypower/secapp/ExampleUnitTest.java b/app/src/test/java/com/xypower/secapp/ExampleUnitTest.java
new file mode 100644
index 0000000..e157ded
--- /dev/null
+++ b/app/src/test/java/com/xypower/secapp/ExampleUnitTest.java
@@ -0,0 +1,17 @@
+package com.xypower.secapp;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see Testing documentation
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..5ae9a7b
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,9 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+plugins {
+ id 'com.android.application' version '7.2.2' apply false
+ id 'com.android.library' version '7.2.2' apply false
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000..71f9eed
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,17 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+# Enables namespacing of each library's R class so that its R class includes only the
+# resources declared in the library itself and none from the library's dependencies,
+# thereby reducing the size of the R class for that library
+android.nonTransitiveRClass=true
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..c8e41ea
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Fri Jun 07 18:36:15 CST 2024
+distributionBase=GRADLE_USER_HOME
+distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-7.3.3-bin.zip
+distributionPath=wrapper/dists
+zipStorePath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
diff --git a/gradlew b/gradlew
new file mode 100644
index 0000000..4f906e0
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,185 @@
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=`expr $i + 1`
+ done
+ case $i in
+ 0) set -- ;;
+ 1) set -- "$args0" ;;
+ 2) set -- "$args0" "$args1" ;;
+ 3) set -- "$args0" "$args1" "$args2" ;;
+ 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=`save "$@"`
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..107acd3
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/key.store b/key.store
new file mode 100644
index 0000000..77ea13f
Binary files /dev/null and b/key.store differ
diff --git a/key.txt b/key.txt
new file mode 100644
index 0000000..2f87316
--- /dev/null
+++ b/key.txt
@@ -0,0 +1,2 @@
+Password: SecApp
+key name secapp
\ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..24c51ed
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,16 @@
+pluginManagement {
+ repositories {
+ gradlePluginPortal()
+ google()
+ mavenCentral()
+ }
+}
+dependencyResolutionManagement {
+ repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+rootProject.name = "SecApp"
+include ':app'