commit c99503af234746a105bbe339c6f6f710a4603257 Author: XI.CHEN Date: Wed Dec 6 10:53:11 2023 +0800 SM2签名和验签还在测试。 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.kts b/app/build.gradle.kts new file mode 100644 index 0000000..e163f43 --- /dev/null +++ b/app/build.gradle.kts @@ -0,0 +1,58 @@ +plugins { + id("com.android.application") +} + +android { + namespace = "com.xinyingpower.testcomm" + compileSdk = 33 + + defaultConfig { + applicationId = "com.xinyingpower.testcomm" + minSdk = 28 + targetSdk = 33 + versionCode = 1 + versionName = "1.1" + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + externalNativeBuild { + cmake { + cppFlags += "-std=c++17" + } + } + } + + buildTypes { + release { + isMinifyEnabled = 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.22.1" + } + } + buildFeatures { + viewBinding = true + } + ndkVersion = "25.1.8937393" + buildToolsVersion = "33.0.1" +} + +dependencies { + + implementation("androidx.appcompat:appcompat:1.6.1") + implementation("com.google.android.material:material:1.8.0") + implementation("androidx.constraintlayout:constraintlayout:2.1.4") + testImplementation("junit:junit:4.13.2") + androidTestImplementation("androidx.test.ext:junit:1.1.5") + androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") +} \ No newline at end of file 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/src/androidTest/java/com/xinyingpower/testcomm/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/xinyingpower/testcomm/ExampleInstrumentedTest.java new file mode 100644 index 0000000..44bbb0d --- /dev/null +++ b/app/src/androidTest/java/com/xinyingpower/testcomm/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.xinyingpower.testcomm; + +import android.content.Context; + +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.ext.junit.runners.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.testcomm", 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..c622cac --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + \ 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..517d2d7 --- /dev/null +++ b/app/src/main/cpp/CMakeLists.txt @@ -0,0 +1,41 @@ +# For more information about using CMake with Android Studio, read the +# documentation: https://d.android.com/studio/projects/add-native-code.html. +# For more examples on how to use CMake, see https://github.com/android/ndk-samples. + +# Sets the minimum CMake version required for this project. +cmake_minimum_required(VERSION 3.22.1) + +# Declares the project name. The project name can be accessed via ${ PROJECT_NAME}, +# Since this is the top level CMakeLists.txt, the project name is also accessible +# with ${CMAKE_PROJECT_NAME} (both CMake variables are in-sync within the top level +# build script scope). +project("testcomm") + +# 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. +# +# In this top level CMakeLists.txt, ${CMAKE_PROJECT_NAME} is used to define +# the target library name; in the sub-module's CMakeLists.txt, ${PROJECT_NAME} +# is preferred for the same purpose. +# +# In order to load a library into your app from Java/Kotlin, you must call +# System.loadLibrary() and pass the name of the library defined here; +# for GameActivity/NativeActivity derived applications, the same library name must be +# used in the AndroidManifest.xml file. +add_library(${CMAKE_PROJECT_NAME} SHARED + # List C/C++ source files with relative paths to this CMakeLists.txt. + SpiPort.cpp + #spi-test-random.cpp + # NRSEC3000ctl.cpp + SpiLib.cpp + native-lib.cpp) + +# Specifies libraries CMake should link to your target library. You +# can link libraries from various origins, such as libraries defined in this +# build script, prebuilt third-party libraries, or Android system libraries. +target_link_libraries(${CMAKE_PROJECT_NAME} + # List libraries link to the target library + android + log) \ No newline at end of file diff --git a/app/src/main/cpp/SerialPort.cpp b/app/src/main/cpp/SerialPort.cpp new file mode 100644 index 0000000..e035c8d --- /dev/null +++ b/app/src/main/cpp/SerialPort.cpp @@ -0,0 +1,142 @@ +/* + * Copyright 2009-2011 Cedric Priscal + * + * 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 + * + * http://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. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "SerialPort.h" + +#include "android/log.h" +static const char *TAG="serial_port"; +#define LOGI(fmt, args...) __android_log_print(ANDROID_LOG_INFO, TAG, fmt, ##args) +#define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, TAG, fmt, ##args) +#define LOGE(fmt, args...) __android_log_print(ANDROID_LOG_ERROR, TAG, fmt, ##args) + +static speed_t getBaudrate(int baudrate) +{ + switch(baudrate) { + case 0: return B0; + case 50: return B50; + case 75: return B75; + case 110: return B110; + case 134: return B134; + case 150: return B150; + case 200: return B200; + case 300: return B300; + case 600: return B600; + case 1200: return B1200; + case 1800: return B1800; + case 2400: return B2400; + case 4800: return B4800; + case 9600: return B9600; + case 19200: return B19200; + case 38400: return B38400; + case 57600: return B57600; + case 115200: return B115200; + case 230400: return B230400; + case 460800: return B460800; + case 500000: return B500000; + case 576000: return B576000; + case 921600: return B921600; + case 1000000: return B1000000; + case 1152000: return B1152000; + case 1500000: return B1500000; + case 2000000: return B2000000; + case 2500000: return B2500000; + case 3000000: return B3000000; + case 3500000: return B3500000; + case 4000000: return B4000000; + default: return -1; + } +} + +/* + * Class: android_serialport_SerialPort + * Method: open + * Signature: (Ljava/lang/String;II)Ljava/io/FileDescriptor; + */ +bool SerialPort::Open(std::string path, int baudrate, int flags) +{ + speed_t speed; + + /* Check arguments */ + { + speed = getBaudrate(baudrate); + if (speed == -1) { + /* TODO: throw an exception */ + LOGE("Invalid baudrate"); + return false; + } + } + + /* Opening device */ + { + + m_fd = open(path.c_str(), O_RDWR | flags); + LOGD("open() m_fd = %d", m_fd); + if (m_fd == -1) + { + /* Throw an exception */ + LOGE("Cannot open port"); + /* TODO: throw an exception */ + return false; + } + } + + /* Configure device */ + { + struct termios cfg; + LOGD("Configuring serial port"); + if (tcgetattr(m_fd, &cfg)) + { + LOGE("tcgetattr() failed"); + close(m_fd); + /* TODO: throw an exception */ + return false; + } + + cfmakeraw(&cfg); + cfsetispeed(&cfg, speed); + cfsetospeed(&cfg, speed); + + if (tcsetattr(m_fd, TCSANOW, &cfg)) + { + LOGE("tcsetattr() failed"); + close(m_fd); + /* TODO: throw an exception */ + return false; + } + } + + return true; +} + +/* + * Class: cedric_serial_SerialPort + * Method: close + * Signature: ()V + */ +bool SerialPort::Close() +{ + LOGD("close(m_fd = %d)", m_fd); + close(m_fd); +} + diff --git a/app/src/main/cpp/SerialPort.h b/app/src/main/cpp/SerialPort.h new file mode 100644 index 0000000..28f603a --- /dev/null +++ b/app/src/main/cpp/SerialPort.h @@ -0,0 +1,18 @@ +#ifndef __SERIALPORT_H__ +#define __SERIALPORT_H__ + +#include + +class SerialPort +{ +public: + + bool Open(std::string path, int, int); + + bool Close(); + +protected: + int m_fd; +}; + +#endif // __SERIALPORT_H__ diff --git a/app/src/main/cpp/SpiLib.cpp b/app/src/main/cpp/SpiLib.cpp new file mode 100644 index 0000000..f2c0663 --- /dev/null +++ b/app/src/main/cpp/SpiLib.cpp @@ -0,0 +1,993 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include "SpiLib.h" +using namespace std; + +#define CMD_HEAD_SIZE 5 +//typedef unsigned char u8; + +#define RE_SUC 0x01 +#define RE_ERROR 0x00 + + + +int SpiLIb::spi_transfer(int fd, unsigned char *txbuf, unsigned char *rxbuf, int bytes) +{ + struct spi_ioc_transfer xfer[2]; + int status; + + memset(xfer, 0, sizeof(xfer)); + + xfer[0].tx_buf = (__u64)txbuf; + xfer[0].rx_buf = (__u64)rxbuf; + xfer[0].len = bytes; + + status = ioctl(fd, SPI_IOC_MESSAGE(1), xfer); + if (status < 0) + { + perror("SPI_IOC_MESSAGE"); + return -1; + } + + return status; + +} + +void SpiLIb::spi_master_init(const char *name, int fd) +{ + __u8 mode = 3; + __u8 lsb, bits; + //__u32 speed = 30000000; + __u32 speed = 2000000; + //__u32 speed = 2000000; + //__u32 speed = 33000000; + + // SPI_IOC_WR_MODE + + ioctl(fd, SPI_IOC_WR_MODE, &mode); + ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); + + if (ioctl(fd, SPI_IOC_RD_MODE, &mode) < 0) + { + perror("SPI rd_mode"); + return; + } + + if (ioctl(fd, SPI_IOC_RD_LSB_FIRST, &lsb) < 0) + { + perror("SPI rd_lsb_fist"); + return; + } + + if (ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits) < 0) + { + perror("SPI rd bits_per_word"); + return; + } + + if (ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed) < 0) + { + perror("SPI rd max_speed_hz"); + return; + } + + __android_log_print(ANDROID_LOG_INFO, "SPi", "%s: spi mode %d, %d bits %sper word, %d Hz max\n", name, mode, bits, lsb ? "(lsb first) " : "", speed); + //printf("%s: spi mode %d, %d bits %sper word, %d Hz max\n", + // name, mode, bits, lsb ? "(lsb first) " : "", speed); +} + +unsigned char SpiLIb::get_crc7(const unsigned char *buff, int len) +{ + unsigned char crc7_accum = 0; + int i; + + for (i=0; i < len; i++) { + crc7_accum = + crc7_table[(crc7_accum << 1) ^ buff[i]]; + } + return crc7_accum; +} + +int SpiLIb::delay(int x) +{ + // while (--x); + // std::this_thread::sleep_for(std::chrono::milliseconds(50)); + usleep(50000); + return 0; +} + + +void SpiLIb::SendCmdHeader(int fd,u8 *cmd, u8 *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(fd, cmd+i, rxbuf+i, 1); + __android_log_print(ANDROID_LOG_INFO, "SPiCMD", "cmd[%d]=%x,rxbuf[%d]=%x",i,*(cmd+i),i, *(rxbuf+i)); + delay(20); + } + + cmd[0]=0xaa; //for response + +} + +void SpiLIb::RcvINS(int fd, u8 *txbuf, u8 *buf, u8 ins) +{ + int retval; + int cnt = 1000; + int count=0; + /* receive ins */ + INS: + txbuf[0] = 0xaa; + delay(20); + while(cnt--) + { + retval = spi_transfer(fd, txbuf, buf, 1); + __android_log_print(ANDROID_LOG_INFO, "SPiINS", "txbuf=%x,buf=%x", *txbuf,*buf); + if(*buf == ins) + { + return; + break; + } + else + goto INS; + } +} + +void SpiLIb::RcvLEN(int fd, u8 *txbuf, u8 *buf, u8 len) +{ + + int retval; + /* receive length */ + LEN: + retval = spi_transfer(fd, txbuf, buf, 1); + __android_log_print(ANDROID_LOG_INFO, "SPiLEN", "txbuf=%x,rxbuf=%hhu", *txbuf,*buf); +} + +//Rcvdata +void SpiLIb::RcvData(int fd, u8 *txbuf, u8 *buf) +{ + int i; + int retval; + + /* receive data and crc */ + for(i=0; i<*(buf-1); i++) + { + + retval = spi_transfer(fd, txbuf, buf+i, 1); + __android_log_print(ANDROID_LOG_INFO, "SPiDATA", "data[%d]=%x",i, *(buf+i)); + } +} + + +//RcvSW +void SpiLIb::RcvSW(int fd, u8 *txbuf, u8 *buf, u8 sw) +{ + int i; + int retval; + + SW90: + /* receive state word */ + delay(20); + while(1) + { + retval = spi_transfer(fd, txbuf, buf, 1); + + __android_log_print(ANDROID_LOG_INFO, "SPiSW", "txbuf=%x,buf=%x", *txbuf,*buf); + + if(*buf != sw) + { + goto SW90; + } + break; + } + retval = spi_transfer(fd, txbuf, buf+1, 1); +} + +void SpiLIb::SendEnd(int fd, u8 *txbuf, u8 *buf) +{ + int retval; + txbuf[0] = 0xaa; + retval = spi_transfer(fd, txbuf, buf, 1); + __android_log_print(ANDROID_LOG_INFO, "SPi_SENDEND", "txbuf=%x,rxbuf=%hhu", *txbuf,*buf); +} + +void SpiLIb::SendId(int fd, u8 *txbuf, u8 *buf, u8 id) +{ + + int retval; + txbuf[0]=id; + retval = spi_transfer(fd, txbuf, buf, 1); + __android_log_print(ANDROID_LOG_INFO, "SPi_SENDID", "txbuf=%x,rxbuf=%hhu", *txbuf,*buf); +} + +void SpiLIb::SendData(int fd,u8 *data, u8 *rxbuf,int data_size) +{ + int i=0; + int retval; + unsigned char crc[1]; + crc[0]= get_crc7(data,data_size); + + for (i=0; i< data_size; i++) + { + retval = spi_transfer(fd, data+i, rxbuf+i, 1); + __android_log_print(ANDROID_LOG_INFO, "SPi_SENDDATA", "i=%d,txbuf=%x,rxbuf=%x", i,*(data+i),*(rxbuf+i)); + delay(20); + } + retval = spi_transfer(fd, crc, rxbuf, 1); + +} + + +int SpiLIb::Spirandom() +{ + int i; + int cnt; + unsigned char txbuf[256]; + unsigned char rxbuf[256]; + + int retval; + int msglen; + int fd; + const char *devname = "/dev/spidevSE"; + + + // NrsecSpiPort spi("/dev/spidevSE"); + // + // // NrsecSpiPort spi("/dev/spidev0.0"); + // devname = "/dev/spidevSE"; + + fd = open(devname, O_RDWR); + if (fd < 0) { + perror("open"); + return 1; + } + spi_master_init(devname, fd); + + + 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)); + + SendCmdHeader(fd, txbuf, rxbuf); + + RcvINS(fd,txbuf,rxbuf,txbuf[1]); // 指令 + + RcvLEN(fd, txbuf,rxbuf+1, txbuf[4]+1); //长度 多加一个字节的 CRC + + RcvData(fd, txbuf, rxbuf+2); + + RcvSW(fd, txbuf, rxbuf+2+rxbuf[1], 0x90); + + //计算接收到数据的CRC + if(get_crc7(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); + __android_log_print(ANDROID_LOG_INFO, "SPi", "rx %1d bytes:", rxbuf[1]+4); + close(fd); + + std::string result = "Random: "; + char output[16] = { 0 }; + for (i = 0; i < rxbuf[1]+4; i++) { + sprintf(output, " %02x ", rxbuf[i]); + result += output; + } + __android_log_print(ANDROID_LOG_INFO, "SPi", "%s", result.c_str()); + // printf("\n"); + + return 0; +} + +int SpiLIb::Version() +{ + int i; + int cnt; + unsigned char txbuf[256]; + unsigned char rxbuf[256]; + + int retval; + int msglen; + int fd; + //const char *devname = "/dev/spidevSE"; + //const char *devname = "/dev/spidev0.0"; + const char *devname = "/dev/mtkgpioctrl"; + + // NrsecSpiPort spi("/dev/spidevSE"); + // + // // NrsecSpiPort spi("/dev/spidev0.0"); + + fd = open(devname, O_RDWR); + if (fd < 0) { + perror("open"); + return 1; + } + spi_master_init(devname, fd); + + + 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, Version_CMD, sizeof(Version_CMD)); + + SendCmdHeader(fd, txbuf, rxbuf); + + RcvINS(fd,txbuf,rxbuf,txbuf[1]); // 指令 + + RcvLEN(fd,txbuf,rxbuf+1, txbuf[4]); //长度 多加一个字节的 CRC + + RcvData(fd, txbuf, rxbuf+2); + + RcvSW(fd, txbuf, rxbuf+2+rxbuf[1], 0x90); + + //计算接收到数据的CRC + if(get_crc7(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); + __android_log_print(ANDROID_LOG_INFO, "SPi", "rx %1d bytes:", rxbuf[1]+4); + std::string result = "Version: "; + char output[16] = { 0 }; + for (i = 0; i < rxbuf[1]+4; i++) { + sprintf(output, " %c ", rxbuf[i]); + result += output; + } + __android_log_print(ANDROID_LOG_INFO, "SPi", "%s", result.c_str()); + //__android_log_print(ANDROID_LOG_INFO, "SPi", "%s", rxbuf); + // printf("\n"); + + close(fd); + return 0; +} + +int SpiLIb::SM2keypair(int index)//产生密钥 +{ + int i; + int cnt; + unsigned char txbuf[256]; + unsigned char rxbuf[256]; + + int retval; + int msglen; + int fd; + const char *devname = "/dev/spidevSE"; + //const char *devname = "/dev/spidev0.0"; + //const char *devname = "/dev/mtkgpioctrl"; + + // NrsecSpiPort spi("/dev/spidevSE"); + // + // // NrsecSpiPort spi("/dev/spidev0.0"); + + fd = open(devname, O_RDWR); + if (fd < 0) { + perror("open"); + return 1; + } + spi_master_init(devname, fd); + + + 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, "SPi", "tx %1d bytes", msglen); + + CMD_RESEND: + + memcpy(txbuf, (const void *) SM2Keypair_CMD, sizeof(SM2Keypair_CMD)); + + SendCmdHeader(fd, txbuf, rxbuf); + + RcvSW(fd, txbuf, rxbuf, 0x90); + + + close(fd); + return 0; +} + +int SpiLIb::SM2OutPub(int index,unsigned char result[])//导出公钥 +{ + int i; + int cnt; + unsigned char txbuf[256]; + unsigned char rxbuf[256]; + + int retval; + int msglen; + int fd; + const char *devname = "/dev/spidevSE"; + //const char *devname = "/dev/spidev0.0"; + //const char *devname = "/dev/mtkgpioctrl"; + + // NrsecSpiPort spi("/dev/spidevSE"); + // + // // NrsecSpiPort spi("/dev/spidev0.0"); + + fd = open(devname, O_RDWR); + if (fd < 0) { + perror("open"); + return 1; + } + spi_master_init(devname, fd); + + + 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)); + + SendCmdHeader(fd, txbuf, rxbuf); + + RcvINS(fd,txbuf,rxbuf,txbuf[1]); // 指令 + + RcvLEN(fd,txbuf,rxbuf+1, txbuf[4]); //长度 多加一个字节的 CRC + + RcvData(fd, txbuf, rxbuf+2); + + RcvSW(fd, txbuf, rxbuf+2+rxbuf[1], 0x90); + + //计算接收到数据的CRC + if(get_crc7(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); + __android_log_print(ANDROID_LOG_INFO, "SPi", "rx %1d bytes:", rxbuf[1]+4); + //std::string result = "SM2公钥: "; + //char output[16] = { 0 }; + for (i = 2; i < rxbuf[1]+2; i++) { + //sprintf(output, " %02x ", rxbuf[i]); + result[i-2]= rxbuf[i]; + } + close(fd); + return 0; +} + +int SpiLIb::SM2OutPri(int index,unsigned char result[])//导出私钥 +{ + int i; + int cnt; + unsigned char txbuf[256]; + unsigned char rxbuf[256]; + + int retval; + int msglen; + int fd; + const char *devname = "/dev/spidevSE"; + //const char *devname = "/dev/spidev0.0"; + //const char *devname = "/dev/mtkgpioctrl"; + + // NrsecSpiPort spi("/dev/spidevSE"); + // + // // NrsecSpiPort spi("/dev/spidev0.0"); + + fd = open(devname, O_RDWR); + if (fd < 0) { + perror("open"); + return 1; + } + spi_master_init(devname, fd); + + + 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, "SPi", "tx %1d bytes", msglen); + + CMD_RESEND: + + memcpy(txbuf, (const void *) SM2OutPri_CMD, sizeof(SM2OutPri_CMD)); + + SendCmdHeader(fd, txbuf, rxbuf); + + RcvINS(fd,txbuf,rxbuf,txbuf[1]); // 指令 + + RcvLEN(fd,txbuf,rxbuf+1, txbuf[4]); //长度 多加一个字节的 CRC + + RcvData(fd, txbuf, rxbuf+2); + + RcvSW(fd, txbuf, rxbuf+2+rxbuf[1], 0x90); + + //计算接收到数据的CRC + if(get_crc7(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); + __android_log_print(ANDROID_LOG_INFO, "SPi", "rx %1d bytes:", rxbuf[1]+4); + + for (i = 2; i < rxbuf[1]+2; i++) { + //sprintf(output, " %02x ", rxbuf[i]); + result[i-2]= rxbuf[i]; + } +// std::string result = "OutPri"; +// char output[16] = { 0 }; +// for (i = 0; i < rxbuf[1]+4; i++) { +// sprintf(output, " %c ", rxbuf[i]); +// result += output; +// } +// __android_log_print(ANDROID_LOG_INFO, "SPi", "%s", result.c_str()); +// //__android_log_print(ANDROID_LOG_INFO, "SPi", "%s", rxbuf); +// // printf("\n"); + + close(fd); + return 0; +} + +int SpiLIb::SM2InPub(int index,const unsigned char new_key[])//外部公钥导入存放在01 +{ + int i; + int cnt; + unsigned char txbuf[256]; + unsigned char rxbuf[256]; + + int retval; + int msglen; + int fd; + const char *devname = "/dev/spidevSE"; + //const char *devname = "/dev/spidev0.0"; + //const char *devname = "/dev/mtkgpioctrl"; + + // NrsecSpiPort spi("/dev/spidevSE"); + // + // // NrsecSpiPort spi("/dev/spidev0.0") + fd = open(devname, O_RDWR); + if (fd < 0) { + perror("open"); + return 1; + } + spi_master_init(devname, fd); + + + 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)); + + SendCmdHeader(fd, txbuf, rxbuf); + + RcvINS(fd,txbuf,rxbuf,txbuf[1]); // 指令 + + SendId(fd,txbuf,rxbuf, 0x55); + + memcpy(txbuf, new_key, 64); + + SendData(fd, txbuf, rxbuf,64); + + SendEnd(fd,txbuf,rxbuf); + + RcvSW(fd, txbuf, rxbuf+1, 0x90); + + std::string result = "InPub: success"; + __android_log_print(ANDROID_LOG_INFO, "SPi", "%s", result.c_str()); + //__android_log_print(ANDROID_LOG_INFO, "SPi", "%s", rxbuf); + // printf("\n"); + + close(fd); + return 0; +} + +int SpiLIb::SM2InPri(int index,const unsigned char new_key[])//导入私钥 没测试 +{ + int i; + int cnt; + unsigned char txbuf[256]; + unsigned char rxbuf[256]; + + int retval; + int msglen; + int fd; + const char *devname = "/dev/spidevSE"; + //const char *devname = "/dev/spidev0.0"; + //const char *devname = "/dev/mtkgpioctrl"; + + // NrsecSpiPort spi("/dev/spidevSE"); + // + // // NrsecSpiPort spi("/dev/spidev0.0"); + + fd = open(devname, O_RDWR); + if (fd < 0) { + perror("open"); + return 1; + } + spi_master_init(devname, fd); + + + 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)); + + SendCmdHeader(fd, txbuf, rxbuf); + + RcvINS(fd,txbuf,rxbuf,txbuf[1]); // 指令 + + SendId(fd,txbuf,rxbuf, 0x55); + + memcpy(txbuf, new_key, 32); + + SendData(fd, txbuf, rxbuf,32); + + SendEnd(fd,txbuf,rxbuf); + + RcvSW(fd, txbuf, rxbuf+1, 0x90); + + std::string result = "InPri: success"; + __android_log_print(ANDROID_LOG_INFO, "SPi", "%s", result.c_str()); + + close(fd); + return 0; +} + +int SpiLIb::SM3Hash(const unsigned char *to_hash ,int len,unsigned char *out_hash)//原始哈希 跑通了,没有验证 +{ + int i; + int cnt; + unsigned char txbuf[256]; + unsigned char rxbuf[256]; + + int retval; + int msglen; + int fd; + const char *devname = "/dev/spidevSE"; + //const char *devname = "/dev/spidev0.0"; + //const char *devname = "/dev/mtkgpioctrl"; + + // NrsecSpiPort spi("/dev/spidevSE"); + // + // // NrsecSpiPort spi("/dev/spidev0.0") + fd = open(devname, O_RDWR); + if (fd < 0) { + perror("open"); + return 1; + } + spi_master_init(devname, fd); + + + msglen = 5; + memset(rxbuf, 0, sizeof(rxbuf)); + memset(txbuf, 0, sizeof(txbuf)); + + int re[4]={0}; // 余数数组 + int x = 0; // 余数数组下标 + int a=len; + while (a != 0) { + re[x] = a % 16; + a /= 16; + x++; + } + SM3Hash_CMD[3]=re[2]+re[3]*16; + SM3Hash_CMD[4]=re[0]+re[1]*16; + __android_log_print(ANDROID_LOG_INFO, "len", "len=%x", len); + //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)); + + SendCmdHeader(fd, txbuf, rxbuf); + + RcvINS(fd,txbuf,rxbuf,txbuf[1]); + + SendId(fd,txbuf,rxbuf, 0x55); + + memcpy(txbuf, to_hash, len); + + SendData(fd, txbuf, rxbuf,len); + + SendEnd(fd,txbuf,rxbuf); + + memcpy(txbuf, (const void *) SM3Hash_CMD, sizeof(SM3Hash_CMD)); + + RcvINS(fd,txbuf,rxbuf,txbuf[1]); + + RcvLEN(fd,txbuf,rxbuf+1, 1); + + RcvData(fd, txbuf, rxbuf+2); + + RcvSW(fd, txbuf, rxbuf+2+rxbuf[1], 0x90);//? + + __android_log_print(ANDROID_LOG_INFO, "SPi", "rx %1d bytes:", rxbuf[1]+4); + for (i = 2; i < rxbuf[1]+2; i++) { + //sprintf(output, " %02x ", rxbuf[i]); + out_hash[i-2]= rxbuf[i]; + } + + close(fd); + return 0; +} + +int SpiLIb::sm3hash_tosm2(unsigned char *in,int inl,unsigned char *out, unsigned char *pubkey, unsigned char +*pucID, int idl) +{ + int nRet,l; + unsigned char *Z = NULL; + int entl = 0; + unsigned char tmpm[32]; + unsigned char 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 = (unsigned char *)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 = (unsigned char *)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 SpiLIb::SM2Sign(int index,const unsigned char *to_sign,unsigned char *out_sign)//SM2签名 所使用的哈希值应该来源于sm3hash_tosm2 +{ + int i; + int cnt; + unsigned char txbuf[256]; + unsigned char rxbuf[256]; + + int retval; + int msglen; + int fd; + const char *devname = "/dev/spidevSE"; + //const char *devname = "/dev/spidev0.0"; + //const char *devname = "/dev/mtkgpioctrl"; + + // NrsecSpiPort spi("/dev/spidevSE"); + // + // // NrsecSpiPort spi("/dev/spidev0.0") + fd = open(devname, O_RDWR); + if (fd < 0) { + perror("open"); + return 1; + } + spi_master_init(devname, fd); + + + 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 *) SM2Sign_CMD, sizeof(SM2Sign_CMD)); + + SendCmdHeader(fd, txbuf, rxbuf); + + RcvINS(fd,txbuf,rxbuf,txbuf[1]); + + SendId(fd,txbuf,rxbuf, 0x55); + + memcpy(txbuf, to_sign, 32); + + SendData(fd, txbuf, rxbuf,32); + + SendEnd(fd,txbuf,rxbuf); + + memcpy(txbuf, (const void *) SM2Sign_CMD, sizeof(SM2Sign_CMD)); + + RcvINS(fd,txbuf,rxbuf,txbuf[1]); + + RcvLEN(fd,txbuf,rxbuf+1, 1); + + RcvData(fd, txbuf, rxbuf+2); + + RcvSW(fd, txbuf, rxbuf+2+rxbuf[1], 0x90); + + __android_log_print(ANDROID_LOG_INFO, "SPi", "rx %1d bytes:", rxbuf[1]+4); + for (i = 2; i < rxbuf[1]+2; i++) { + //sprintf(output, " %02x ", rxbuf[i]); + out_sign[i-2]= rxbuf[i]; + } + + close(fd); + return 0; +} + +int SpiLIb::SM2VerifySign(int index, unsigned char *hash,unsigned char *vs)//SM2验签 +{ + unsigned char txbuf[256]; + unsigned char rxbuf[256]; + + int retval; + int msglen; + int fd; + const char *devname = "/dev/spidevSE"; + //const char *devname = "/dev/spidev0.0"; + //const char *devname = "/dev/mtkgpioctrl"; + + // NrsecSpiPort spi("/dev/spidevSE"); + // + // // NrsecSpiPort spi("/dev/spidev0.0") + fd = open(devname, O_RDWR); + if (fd < 0) { + perror("open"); + return 1; + } + spi_master_init(devname, fd); + + + 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 *) SM2VerifySign_CMD, sizeof(SM2VerifySign_CMD)); + + SendCmdHeader(fd, txbuf, rxbuf); + + RcvINS(fd,txbuf,rxbuf,txbuf[1]); + + SendId(fd,txbuf,rxbuf, 0x55); + + memcpy(txbuf, hash, 32); + memcpy(txbuf+32,vs,64); + + SendData(fd, txbuf, rxbuf,96); + + SendEnd(fd,txbuf,rxbuf); + + RcvSW(fd, txbuf, rxbuf, 0x90); + + __android_log_print(ANDROID_LOG_INFO, "SPi", "rx %1d bytes:", rxbuf[1]+4); + + + close(fd); + return 0; +} + diff --git a/app/src/main/cpp/SpiLib.h b/app/src/main/cpp/SpiLib.h new file mode 100644 index 0000000..30ac94c --- /dev/null +++ b/app/src/main/cpp/SpiLib.h @@ -0,0 +1,100 @@ +#ifndef TESTCOMM_SPILIB_H +#define TESTCOMM_SPILIB_H +using namespace std; +typedef unsigned char u8; + +class SpiLIb{ +public: + int Spirandom(); + int Version(); + int SM2keypair(int index); + int SM2OutPub(int index,unsigned char result[]); + int SM2OutPri(int index,unsigned char result[]); + int SM2InPub(int index,const unsigned char new_key[]); + int SM2InPri(int index,const unsigned char new_key[]); + int SM3Hash(const unsigned char *to_hash ,int len,unsigned char *out_hash); + int sm3hash_tosm2(unsigned char *in,int inl,unsigned char *out, unsigned char *pubkey, unsigned char + *pucID, int idl); + int SM2Sign(int index,const unsigned char *to_sign,unsigned char *out_sign); + int SM2VerifySign(int index,unsigned char *hash,unsigned char *vs) + + + +private: + const unsigned char 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 + }; + const unsigned char EK_CMD[5]={0x80,0xd4,0x01,0x00,0x10}; + const unsigned char AK_CMD[5]={0x80,0xd4,0x02,0x00,0x10}; + const unsigned char IV_CMD[5]={0x80,0xd4,0x04,0x00,0x10}; + volatile unsigned char SM1encrpt_CMD[5]={0xa0,0xe0,0x80,0xff,0xff}; + volatile unsigned char SM1decoder_CMD[5]={0xa0,0xe0,0x81,0xff,0xff}; + volatile unsigned char SM2Keypair_CMD[5]={0x80,0xb2,0x00,0xff,0x00}; + volatile unsigned char SM2OutPub_CMD[5]={0x80,0xb8,0x01,0xff,0x40}; + volatile unsigned char SM2OutPri_CMD[5]={0x80,0xb8,0x02,0xff,0x20}; + volatile unsigned char SM2InPub_CMD[5]={0x80,0xba,0x01,0xff,0x40}; + volatile unsigned char SM2InPri_CMD[5]={0x80,0xba,0x02,0xff,0x20}; + volatile unsigned char SM3Hash_CMD[5]={0x80,0xb5,0x00,0xff,0xff}; + volatile unsigned char SM2Sign_CMD[5]={0x80,0xb4,0x00,0xff,0x20}; + volatile unsigned char SM2VerifySign_CMD[5]={0x80,0xb6,0x00,0xff,0x60}; + volatile unsigned char SM2encrypt_CMD[5]={0x80,0xb3,0x01,0xff,0x20}; + volatile unsigned char SM2decoder_CMD[5]={0x80,0xb3,0x81,0xff,0x80}; + volatile unsigned char SM2cert_CMD[5]={0x80,0xb7,0xff,0xff,0xff}; + volatile unsigned char Random_CMD[5]={0x00,0x84,0x00,0x00,0xff}; + const unsigned char Version_CMD[5]={0x00,0x5b,0x00,0x00,0x40}; + const unsigned char Indentify_CMD[5]={0x80,0xb3,0x01,0x04,0x20}; + + int spi_transfer(int fd, unsigned char *txbuf, unsigned char *rxbuf, int bytes); + void spi_master_init(const char *name, int fd); + unsigned char get_crc7(const unsigned char *buff, int len); + void SendCmdHeader(int fd,u8 *cmd, u8 *rxbuf); + int delay(int x); + void RcvINS(int fd, u8 *txbuf, u8 *buf, u8 ins); + void RcvLEN(int fd, u8 *txbuf, u8 *buf, u8 len); + void RcvData(int fd, u8 *txbuf, u8 *buf); + void RcvSW(int fd, u8 *txbuf, u8 *buf, u8 sw); + void SendEnd(int fd, u8 *txbuf, u8 *buf); + void SendId(int fd, u8 *txbuf, u8 *buf, u8 id); + void SendData(int fd,u8 *data, u8 *rxbuf,int data_size); + + + + + +}; + + + + +#endif //TESTCOMM_SPILIB_H diff --git a/app/src/main/cpp/SpiPort.cpp b/app/src/main/cpp/SpiPort.cpp new file mode 100644 index 0000000..dc1be55 --- /dev/null +++ b/app/src/main/cpp/SpiPort.cpp @@ -0,0 +1,61 @@ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "SpiPort.h" + +SpiPort::SpiPort(const std::string& path) : m_path(path), m_fd(0) +{ +} + +SpiPort::~SpiPort() +{ + if (m_fd > 0) + { + close(m_fd); + } +} + +bool SpiPort::Open() +{ + if(m_fd <= 0) m_fd = open(m_path.c_str(), O_RDWR/*|O_NDELAY|O_NOCTTY*/); + if(m_fd <= 0 ) { + int err = errno; + m_log = "open spi Error errno=" + std::to_string(err); + __android_log_print(ANDROID_LOG_INFO, "SPi", "open spi Error errno=%d", err); + return false; + } + else __android_log_print(ANDROID_LOG_INFO, "SPi", "open spi Success m_fd=%d",m_fd); + + return true; +} + +// write +int SpiPort::Write(unsigned char *buf, int len) +{ + return write(m_fd, buf, len); +} + +// read +int SpiPort::Read(unsigned char *buf, int len) +{ + return read(m_fd, buf, len); +} + +//close +bool SpiPort::Close() +{ + if(m_fd > 0) + { + close(m_fd); + m_fd = 0; + } + + return true; +} \ No newline at end of file diff --git a/app/src/main/cpp/SpiPort.h b/app/src/main/cpp/SpiPort.h new file mode 100644 index 0000000..a568d08 --- /dev/null +++ b/app/src/main/cpp/SpiPort.h @@ -0,0 +1,30 @@ +#ifndef _SPIPORT_H_ +#define _SPIPORT_H_ + +#include + +class SpiPort +{ +public: + + SpiPort(const std::string& path); + ~SpiPort(); + + bool Open(); + int Write(unsigned char *buf, int len); + int Read(unsigned char *buf, int len); + + bool Close(); + + std::string GetLog() const + { + return m_log; + } + +protected: + std::string m_path; + std::string m_log; + int m_fd; +}; + +#endif \ No newline at end of file diff --git a/app/src/main/cpp/native-lib.cpp b/app/src/main/cpp/native-lib.cpp new file mode 100644 index 0000000..d2b5db0 --- /dev/null +++ b/app/src/main/cpp/native-lib.cpp @@ -0,0 +1,135 @@ +#include +#include +#include "SpiPort.h" +#include "SpiLib.h" + +#include +#include +#include +#include +#include + +int testSpi(); +int testVersion(); + + +class NrsecSpiPort : public SpiPort { +public: + NrsecSpiPort(const std::string& path) : SpiPort(path) { + + } + + bool Open() + { + if (!SpiPort::Open()) + { + return false; + } + + uint8_t mode = SPI_MODE_3; + uint8_t bits = 8; + uint32_t speed = 33000000; + uint8_t lsb = 1; + // const char *device = "/dev/spidev32766.1"; + + if (ioctl(m_fd, SPI_IOC_WR_MODE, &mode) == -1 || + ioctl(m_fd, SPI_IOC_WR_BITS_PER_WORD, &bits) == -1 || + ioctl(m_fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed) == -1 || + ioctl(m_fd, SPI_IOC_WR_LSB_FIRST, &lsb) == -1) + { + Close(); + return false; + } + + return true; + } + bool GenKeyPair(int keyIdx) { + unsigned char header[] = {0x80, 0xb2, 0x00, (unsigned char)keyIdx, 0x00 }; + + int bytesWriten = Write(header, sizeof(header)); + unsigned char buffer[2] = { 0 }; + int bytesRead = Read(buffer, sizeof(buffer)); + if (bytesRead > 0) { + int aa = 0; + } else { + int bb = 0; + } + + return true; + } +}; + +extern "C" JNIEXPORT jstring JNICALL +Java_com_xinyingpower_testcomm_MainActivity_stringFromJNI( + JNIEnv* env, + jobject /* this */) { + std::string hello = "Hello from C++"; + return env->NewStringUTF(hello.c_str()); +} + +extern "C" JNIEXPORT jstring JNICALL +Java_com_xinyingpower_testcomm_MainActivity_testSpi( + JNIEnv* env, + jobject /* this */, jint port) { + //testSpi(); + SpiLIb a; + const unsigned char newkey[64]={0xaf,0x0c,0xa9,0x40,0x1f,0xe6,0xee,0x0f,0x4c, + 0xfb,0xf7,0x17,0x71,0xde,0x61,0x59 +// ,0x0a,0x05,0x77, +// 0xfa,0xe7,0xd1,0x8d,0x10,0x3a,0x79,0x23,0xf2,0xb3, +// 0x6d,0xea,0x8e,0xe0,0x64,0xe7,0x5d,0x49,0x84,0xe4, +// 0x5f,0xc9,0x07,0x03,0x52,0x33,0x79,0x87,0xd4,0x62, +// 0x62,0xc0,0xcc,0xf0,0xd6,0x85,0x20,0x7f,0x7a,0xe8, +// 0xc8,0xed,0x12,0xdb,0xdc + }; + unsigned char outpub[32]; + //a.SM2keypair(0x00); + a.SM3Hash(newkey,16, outpub); + for (int i = 0; i < 32; i++) { + //sprintf(output, " %02x ", rxbuf[i]); + __android_log_print(ANDROID_LOG_INFO, "SPi", "%02x", outpub[i]); + } + + //a.SM3Hash(0x00,0x10,newkey); + //testVersion(); + + return env->NewStringUTF("End"); + + // NrsecSpiPort spi("/dev/mtkgpioctrl"); + NrsecSpiPort spi("/dev/spidevSE"); + + // NrsecSpiPort spi("/dev/spidev0.0"); + + if (!spi.Open()) { + return env->NewStringUTF(spi.GetLog().c_str()); + } + + spi.GenKeyPair(0); + + unsigned char header[] = { 0x00, 0x5b, 0x00, 0x00, 0x40 }; + + int bytesWriten = spi.Write(header, sizeof(header)); + unsigned char buffer[1024] = { 0 }; + int bytesRead = spi.Read(buffer, 1); + if (bytesRead > 0) { + int aa = 0; + } else { + int bb = 0; + } + int len = buffer[0]; + bytesRead += spi.Read(&buffer[1], len); + + spi.Close(); + + std::string result; + char buf[32] = { 0 }; + for (int idx = 0; idx < 32; idx++) + { + sprintf(buf, "%X ", buffer[idx]); + result += buf; + } + + + + return env->NewStringUTF(result.c_str()); +} \ No newline at end of file diff --git a/app/src/main/cpp/spi-test-random.cpp b/app/src/main/cpp/spi-test-random.cpp new file mode 100644 index 0000000..22bf972 --- /dev/null +++ b/app/src/main/cpp/spi-test-random.cpp @@ -0,0 +1,426 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include + +#define CMD_HEAD_SIZE 5 +typedef unsigned char u8; + +#define RE_SUC 0x01 +#define RE_ERROR 0x00 + +const unsigned char 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 +}; + +const unsigned char EK_CMD[5]={0x80,0xd4,0x01,0x00,0x10}; +const unsigned char AK_CMD[5]={0x80,0xd4,0x02,0x00,0x10}; +const unsigned char IV_CMD[5]={0x80,0xd4,0x04,0x00,0x10}; +volatile unsigned char SM1encrpt_CMD[5]={0xa0,0xe0,0x80,0xff,0xff}; +volatile unsigned char SM1decoder_CMD[5]={0xa0,0xe0,0x81,0xff,0xff}; +volatile unsigned char SM2Keypair_CMD[5]={0x80,0xb2,0x00,0xff,0x00}; +volatile unsigned char SM2OutPub_CMD[5]={0x80,0xb8,0x01,0xff,0x40}; +volatile unsigned char SM2OutPri_CMD[5]={0x80,0xb8,0x02,0xff,0x20}; +volatile unsigned char SM2InPub_CMD[5]={0x80,0xba,0x01,0xff,0x40}; +volatile unsigned char SM2InPri_CMD[5]={0x80,0xba,0x02,0xff,0x20}; +volatile unsigned char SM3Hash_CMD[5]={0x80,0xb5,0x00,0xff,0xff}; +volatile unsigned char SM2Sign_CMD[5]={0x80,0xb4,0x00,0xff,0x20}; +volatile unsigned char SM2VerifySign_CMD[5]={0x80,0xb6,0x00,0xff,0x60}; +volatile unsigned char SM2encrypt_CMD[5]={0x80,0xb3,0x01,0xff,0x20}; +volatile unsigned char SM2decoder_CMD[5]={0x80,0xb3,0x81,0xff,0x80}; +volatile unsigned char SM2cert_CMD[5]={0x80,0xb7,0xff,0xff,0xff}; +volatile unsigned char Random_CMD[5]={0x00,0x84,0x00,0x00,0xff}; +const unsigned char Version_CMD[5]={0x00,0x5b,0x00,0x00,0x40}; +const unsigned char Indentify_CMD[5]={0x80,0xb3,0x01,0x04,0x20}; + +int spi_transfer(int fd, unsigned char *txbuf, unsigned char *rxbuf, int bytes) +{ + struct spi_ioc_transfer xfer[2]; + int status; + + memset(xfer, 0, sizeof(xfer)); + + xfer[0].tx_buf = (__u64)txbuf; + xfer[0].rx_buf = (__u64)rxbuf; + xfer[0].len = bytes; + + status = ioctl(fd, SPI_IOC_MESSAGE(1), xfer); + if (status < 0) + { + perror("SPI_IOC_MESSAGE"); + return -1; + } + + return status; + +} + +void spi_master_init(const char *name, int fd) +{ + __u8 mode = 3; + __u8 lsb, bits; + //__u32 speed = 30000000; + __u32 speed = 2000000; + //__u32 speed = 2000000; + //__u32 speed = 33000000; + + // SPI_IOC_WR_MODE + + ioctl(fd, SPI_IOC_WR_MODE, &mode); + ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); + + if (ioctl(fd, SPI_IOC_RD_MODE, &mode) < 0) + { + perror("SPI rd_mode"); + return; + } + + if (ioctl(fd, SPI_IOC_RD_LSB_FIRST, &lsb) < 0) + { + perror("SPI rd_lsb_fist"); + return; + } + + if (ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits) < 0) + { + perror("SPI rd bits_per_word"); + return; + } + + if (ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed) < 0) + { + perror("SPI rd max_speed_hz"); + return; + } + + __android_log_print(ANDROID_LOG_INFO, "SPi", "%s: spi mode %d, %d bits %sper word, %d Hz max\n", name, mode, bits, lsb ? "(lsb first) " : "", speed); + //printf("%s: spi mode %d, %d bits %sper word, %d Hz max\n", + // name, mode, bits, lsb ? "(lsb first) " : "", speed); +} + +unsigned char get_crc7(const unsigned char *buff, int len) +{ + unsigned char crc7_accum = 0; + int i; + + for (i=0; i < len; i++) { + crc7_accum = + crc7_table[(crc7_accum << 1) ^ buff[i]]; + } + return crc7_accum; +} + +int delay(int x) +{ + // while (--x); + // std::this_thread::sleep_for(std::chrono::milliseconds(50)); + usleep(50000); + return 0; +} + +void delay_us(int x) +{ + usleep(x); +}; + +void SendCmdHeader(int fd,u8 *cmd, u8 *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(fd, cmd+i, rxbuf+i, 1); + __android_log_print(ANDROID_LOG_INFO, "SPiCMD", "cmd[%d]=%x,rxbuf[%d]=%x",i,*(cmd+i),i, *(rxbuf+i)); + delay(20); + } + + cmd[0]=0xaa; //for response + +} + +void RcvINS(int fd, u8 *txbuf, u8 *buf, u8 ins) +{ + int retval; + int cnt = 1000; + int count=0; + /* receive ins */ +INS: + txbuf[0] = 0xaa; + delay(20); + while(cnt--) + { + retval = spi_transfer(fd, txbuf, buf, 1); + __android_log_print(ANDROID_LOG_INFO, "SPiINS", "txbuf=%x,buf=%x", *txbuf,*buf); + if(*buf == ins) + { + return; + break; + } + else + goto INS; + } +} + +void RcvLEN(int fd, u8 *txbuf, u8 *buf, u8 len) +{ + + int retval; + /* receive length */ +LEN: + retval = spi_transfer(fd, txbuf, buf, 1); + __android_log_print(ANDROID_LOG_INFO, "SPiLEN", "txbuf=%x,rxbuf=%hhu", *txbuf,*buf); +} + +//Rcvdata +void RcvData(int fd, u8 *txbuf, u8 *buf) +{ + int i; + int retval; + + /* receive data and crc */ + for(i=0; i<*(buf-1); i++) + { + + retval = spi_transfer(fd, txbuf, buf+i, 1); + __android_log_print(ANDROID_LOG_INFO, "SPiDATA", "data[%d]=%x",i, *(buf+i)); + } +} + + +//RcvSW +void RcvSW(int fd, u8 *txbuf, u8 *buf, u8 sw) +{ + int i; + int retval; + +SW90: + /* receive state word */ + delay(20); + while(1) + { + retval = spi_transfer(fd, txbuf, buf, 1); + if(*buf != sw) + { + goto SW90; + } + break; + } + retval = spi_transfer(fd, txbuf, buf+1, 1); +} + + +int testSpi() +{ + int i; + int cnt; + unsigned char txbuf[256]; + unsigned char rxbuf[256]; + + int retval; + int msglen; + int fd; + const char *devname = "/dev/spidevSE"; + + + // NrsecSpiPort spi("/dev/spidevSE"); + // + // // NrsecSpiPort spi("/dev/spidev0.0"); + // devname = "/dev/spidevSE"; + + fd = open(devname, O_RDWR); + if (fd < 0) { + perror("open"); + return 1; + } + spi_master_init(devname, fd); + + + msglen = 5; + memset(rxbuf, 0, sizeof(rxbuf)); + memset(txbuf, 0, sizeof(txbuf)); + + printf("tx %1d bytes: ", msglen); + +CMD_RESEND: + txbuf[0] = 0x00; + txbuf[1] = 0x84; + txbuf[2] = 0x00; + txbuf[3] = 0x00; + txbuf[4] = 0x08; + + SendCmdHeader(fd, txbuf, rxbuf); + + RcvINS(fd,txbuf,rxbuf,txbuf[1]); // 指令 + + RcvLEN(fd, txbuf,rxbuf+1, txbuf[4]+1); //长度 多加一个字节的 CRC + + RcvData(fd, txbuf, rxbuf+2); + + RcvSW(fd, txbuf, rxbuf+2+rxbuf[1], 0x90); + + //计算接收到数据的CRC + if(get_crc7(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); + __android_log_print(ANDROID_LOG_INFO, "SPi", "rx %1d bytes:", rxbuf[1]+4); + close(fd); + + std::string result = "Random: "; + char output[16] = { 0 }; + for (i = 0; i < rxbuf[1]+4; i++) { + sprintf(output, " %02x ", rxbuf[i]); + result += output; + } + __android_log_print(ANDROID_LOG_INFO, "SPi", "%s", result.c_str()); + // printf("\n"); + + return 0; +} + +int testVersion() +{ + int i; + int cnt; + unsigned char txbuf[256]; + unsigned char rxbuf[256]; + + int retval; + int msglen; + int fd; + //const char *devname = "/dev/spidevSE"; + //const char *devname = "/dev/spidev0.0"; + const char *devname = "/dev/mtkgpioctrl"; + + // NrsecSpiPort spi("/dev/spidevSE"); + // + // // NrsecSpiPort spi("/dev/spidev0.0"); + + fd = open(devname, O_RDWR); + if (fd < 0) { + perror("open"); + return 1; + } + spi_master_init(devname, fd); + + + 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, Version_CMD, sizeof(Version_CMD)); + + SendCmdHeader(fd, txbuf, rxbuf); + + RcvINS(fd,txbuf,rxbuf,txbuf[1]); // 指令 + + RcvLEN(fd,txbuf,rxbuf+1, txbuf[4]); //长度 多加一个字节的 CRC + + RcvData(fd, txbuf, rxbuf+2); + + RcvSW(fd, txbuf, rxbuf+2+rxbuf[1], 0x90); + + //计算接收到数据的CRC + if(get_crc7(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); + __android_log_print(ANDROID_LOG_INFO, "SPi", "rx %1d bytes:", rxbuf[1]+4); + std::string result = "Version: "; + char output[16] = { 0 }; + for (i = 0; i < rxbuf[1]+4; i++) { + sprintf(output, " %c ", rxbuf[i]); + result += output; + } + __android_log_print(ANDROID_LOG_INFO, "SPi", "%s", result.c_str()); + //__android_log_print(ANDROID_LOG_INFO, "SPi", "%s", rxbuf); + // printf("\n"); + + close(fd); + return 0; +} + + diff --git a/app/src/main/cpp/test b/app/src/main/cpp/test new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/java/com/xinyingpower/testcomm/MainActivity.java b/app/src/main/java/com/xinyingpower/testcomm/MainActivity.java new file mode 100644 index 0000000..e731c73 --- /dev/null +++ b/app/src/main/java/com/xinyingpower/testcomm/MainActivity.java @@ -0,0 +1,59 @@ +package com.xinyingpower.testcomm; + +import androidx.appcompat.app.AppCompatActivity; + +import android.os.Bundle; +import android.os.Handler; +import android.view.View; +import android.widget.TextView; + +import com.xinyingpower.testcomm.databinding.ActivityMainBinding; + +public class MainActivity extends AppCompatActivity { + + // Used to load the 'testcomm' library on application startup. + static { + System.loadLibrary("testcomm"); + } + + private ActivityMainBinding binding; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + binding = ActivityMainBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + + // Example of a call to a native method + TextView tv = binding.sampleText; + // tv.setText(stringFromJNI()); + + binding.btnSpi.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + String str = testSpi(0); + binding.sampleText.setText(str); + } + }); + + Handler handler = new Handler(); + Runnable runnable = new Runnable() { + @Override + public void run() { + binding.btnSpi.performClick(); + } + }; + handler.postDelayed(runnable, 1000); + } + + + + /** + * A native method that is implemented by the 'testcomm' native library, + * which is packaged with this application. + */ + public native String stringFromJNI(); + + public native String testSpi(int port); +} \ 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/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ 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..458f1c5 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,28 @@ + + + + + +