@onekeyfe/react-native-lite-card 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +37 -0
  3. package/ReactNativeLiteCard.podspec +22 -0
  4. package/android/build.gradle +79 -0
  5. package/android/gradle.properties +5 -0
  6. package/android/src/main/AndroidManifest.xml +2 -0
  7. package/android/src/main/config/command.json +205 -0
  8. package/android/src/main/cpp/CMakeLists.txt +19 -0
  9. package/android/src/main/cpp/validation.c +227 -0
  10. package/android/src/main/cpp/validation.h +19 -0
  11. package/android/src/main/java/com/onekeyfe/reactnativelitecard/LoggerManager.kt +35 -0
  12. package/android/src/main/java/com/onekeyfe/reactnativelitecard/ReactNativeLiteCardModule.kt +420 -0
  13. package/android/src/main/java/com/onekeyfe/reactnativelitecard/ReactNativeLiteCardPackage.kt +33 -0
  14. package/android/src/main/java/com/onekeyfe/reactnativelitecard/keys/KeysNativeProvider.kt +13 -0
  15. package/android/src/main/java/com/onekeyfe/reactnativelitecard/nfc/Exceptions.kt +58 -0
  16. package/android/src/main/java/com/onekeyfe/reactnativelitecard/nfc/NfcUtils.kt +142 -0
  17. package/android/src/main/java/com/onekeyfe/reactnativelitecard/nfc/broadcast/NfcStatusChangeBroadcastReceiver.kt +56 -0
  18. package/android/src/main/java/com/onekeyfe/reactnativelitecard/nfc/gpchannel/GPChannelNatives.kt +32 -0
  19. package/android/src/main/java/com/onekeyfe/reactnativelitecard/onekeyLite/NfcConstant.kt +38 -0
  20. package/android/src/main/java/com/onekeyfe/reactnativelitecard/onekeyLite/OnekeyLiteCard.kt +236 -0
  21. package/android/src/main/java/com/onekeyfe/reactnativelitecard/onekeyLite/entitys/APDUParam.kt +17 -0
  22. package/android/src/main/java/com/onekeyfe/reactnativelitecard/onekeyLite/entitys/CardInfo.java +84 -0
  23. package/android/src/main/java/com/onekeyfe/reactnativelitecard/onekeyLite/entitys/CardResponse.java +37 -0
  24. package/android/src/main/java/com/onekeyfe/reactnativelitecard/onekeyLite/entitys/CardState.kt +10 -0
  25. package/android/src/main/java/com/onekeyfe/reactnativelitecard/onekeyLite/entitys/ParsedCertInfo.java +39 -0
  26. package/android/src/main/java/com/onekeyfe/reactnativelitecard/onekeyLite/entitys/SecureChanelParam.java +113 -0
  27. package/android/src/main/java/com/onekeyfe/reactnativelitecard/onekeyLite/entitys/SendResponse.kt +26 -0
  28. package/android/src/main/java/com/onekeyfe/reactnativelitecard/onekeyLite/nfc/CommandGenerator.kt +178 -0
  29. package/android/src/main/java/com/onekeyfe/reactnativelitecard/onekeyLite/nfc/Connection.kt +439 -0
  30. package/android/src/main/java/com/onekeyfe/reactnativelitecard/onekeyLite/nfc/GPCAPDUGenerator.kt +56 -0
  31. package/android/src/main/java/com/onekeyfe/reactnativelitecard/utils/EventUtils.kt +14 -0
  32. package/android/src/main/java/com/onekeyfe/reactnativelitecard/utils/GpsUtil.kt +38 -0
  33. package/android/src/main/java/com/onekeyfe/reactnativelitecard/utils/HexUtils.java +93 -0
  34. package/android/src/main/java/com/onekeyfe/reactnativelitecard/utils/LogUtil.kt +11 -0
  35. package/android/src/main/java/com/onekeyfe/reactnativelitecard/utils/MiUtil.kt +93 -0
  36. package/android/src/main/java/com/onekeyfe/reactnativelitecard/utils/NfcPermissionUtils.kt +24 -0
  37. package/android/src/main/java/com/onekeyfe/reactnativelitecard/utils/Utils.java +437 -0
  38. package/android/src/main/jniLibs/arm64-v8a/libgpchannelNDK.so +0 -0
  39. package/android/src/main/jniLibs/armeabi-v7a/libgpchannelNDK.so +0 -0
  40. package/ios/Classes/OKLiteCommand/OKLiteCommandModal.h +39 -0
  41. package/ios/Classes/OKLiteCommand/OKLiteCommandModal.m +143 -0
  42. package/ios/Classes/OKLiteCommand/OKLiteCommandTool.h +28 -0
  43. package/ios/Classes/OKLiteCommand/OKLiteCommandTool.m +53 -0
  44. package/ios/Classes/OKNFCBridge.h +28 -0
  45. package/ios/Classes/OKNFCBridge.mm +221 -0
  46. package/ios/Classes/OKNFCLiteDefine.h +108 -0
  47. package/ios/Classes/OKNFTLite/OKLiteProtocol.h +37 -0
  48. package/ios/Classes/OKNFTLite/OKLiteV1.h +41 -0
  49. package/ios/Classes/OKNFTLite/OKLiteV1.m +609 -0
  50. package/ios/Classes/OKNFTLite/OKLiteV2.h +17 -0
  51. package/ios/Classes/OKNFTLite/OKLiteV2.m +132 -0
  52. package/ios/Classes/OKNFTLite/OKNFCManager.h +40 -0
  53. package/ios/Classes/OKNFTLite/OKNFCManager.m +330 -0
  54. package/ios/Classes/Utils/NFCConfig.h +19 -0
  55. package/ios/Classes/Utils/NFCConfig.m +18 -0
  56. package/ios/Classes/Utils/NSData+OKNFCHexData.h +17 -0
  57. package/ios/Classes/Utils/NSData+OKNFCHexData.m +24 -0
  58. package/ios/Classes/Utils/NSData+StringToData.h +12 -0
  59. package/ios/Classes/Utils/NSData+StringToData.m +25 -0
  60. package/ios/Classes/Utils/NSString+OKAdd.h +14 -0
  61. package/ios/Classes/Utils/NSString+OKAdd.m +40 -0
  62. package/ios/Classes/Utils/NSString+OKNFCHexStr.h +18 -0
  63. package/ios/Classes/Utils/NSString+OKNFCHexStr.m +38 -0
  64. package/ios/Classes/Utils/OKNFCUtility.h +18 -0
  65. package/ios/Classes/Utils/OKNFCUtility.m +22 -0
  66. package/ios/Classes/Utils/OKTools.h +17 -0
  67. package/ios/Classes/Utils/OKTools.m +21 -0
  68. package/ios/GPChannelSDKCore.xcframework/Info.plist +52 -0
  69. package/ios/GPChannelSDKCore.xcframework/ios-arm64/GPChannelSDKCore.framework/GPChannelSDKCore +0 -0
  70. package/ios/GPChannelSDKCore.xcframework/ios-arm64/GPChannelSDKCore.framework/Headers/GPChannelSDK.h +315 -0
  71. package/ios/GPChannelSDKCore.xcframework/ios-arm64/GPChannelSDKCore.framework/Headers/GPChannelSDKCore.h +19 -0
  72. package/ios/GPChannelSDKCore.xcframework/ios-arm64/GPChannelSDKCore.framework/Info.plist +0 -0
  73. package/ios/GPChannelSDKCore.xcframework/ios-arm64/GPChannelSDKCore.framework/Modules/module.modulemap +7 -0
  74. package/ios/GPChannelSDKCore.xcframework/ios-arm64/GPChannelSDKCore.framework/_CodeSignature/CodeResources +147 -0
  75. package/ios/GPChannelSDKCore.xcframework/ios-arm64_x86_64-simulator/GPChannelSDKCore.framework/GPChannelSDKCore +0 -0
  76. package/ios/GPChannelSDKCore.xcframework/ios-arm64_x86_64-simulator/GPChannelSDKCore.framework/Headers/GPChannelSDK.h +315 -0
  77. package/ios/GPChannelSDKCore.xcframework/ios-arm64_x86_64-simulator/GPChannelSDKCore.framework/Headers/GPChannelSDKCore.h +19 -0
  78. package/ios/GPChannelSDKCore.xcframework/ios-arm64_x86_64-simulator/GPChannelSDKCore.framework/Info.plist +0 -0
  79. package/ios/GPChannelSDKCore.xcframework/ios-arm64_x86_64-simulator/GPChannelSDKCore.framework/Modules/module.modulemap +7 -0
  80. package/ios/GPChannelSDKCore.xcframework/ios-arm64_x86_64-simulator/GPChannelSDKCore.framework/_CodeSignature/CodeResources +147 -0
  81. package/ios/ReactNativeLiteCard.h +5 -0
  82. package/ios/ReactNativeLiteCard.mm +222 -0
  83. package/lib/module/NativeReactNativeLiteCard.js +25 -0
  84. package/lib/module/NativeReactNativeLiteCard.js.map +1 -0
  85. package/lib/module/index.js +71 -0
  86. package/lib/module/index.js.map +1 -0
  87. package/lib/module/package.json +1 -0
  88. package/lib/typescript/package.json +1 -0
  89. package/lib/typescript/src/NativeReactNativeLiteCard.d.ts +59 -0
  90. package/lib/typescript/src/NativeReactNativeLiteCard.d.ts.map +1 -0
  91. package/lib/typescript/src/index.d.ts +23 -0
  92. package/lib/typescript/src/index.d.ts.map +1 -0
  93. package/package.json +168 -0
  94. package/src/NativeReactNativeLiteCard.ts +112 -0
  95. package/src/index.tsx +94 -0
@@ -0,0 +1,178 @@
1
+ package so.onekey.app.wallet.lite.onekeyLite.nfc
2
+
3
+ import com.google.gson.JsonObject
4
+ import com.google.gson.JsonParser
5
+ import org.haobtc.onekey.card.gpchannel.GPChannelNatives.nativeGPCParseAPDUResponse
6
+ import org.haobtc.onekey.card.gpchannel.GPChannelNatives.nativeGPCParseSafeAPDUResponse
7
+ import so.onekey.app.wallet.lite.nfc.NFCExceptions
8
+ import so.onekey.app.wallet.lite.onekeyLite.entitys.APDUParam
9
+ import so.onekey.app.wallet.lite.onekeyLite.entitys.CardResponse
10
+ import so.onekey.app.wallet.lite.onekeyLite.entitys.SendResponse
11
+ import so.onekey.app.wallet.lite.utils.Utils
12
+
13
+ enum class AppleCardType(val aid: String, val prefixSN: String) {
14
+ V1("D156000132834001", "OKLFT"),
15
+ V2("6f6e656b65792e6261636b757001", "OKLFB"),
16
+ }
17
+
18
+ enum class CommandArea(val code: String) {
19
+ None("none"), BackupApplet("backup"), PrimarySafety("master");
20
+
21
+ companion object {
22
+ fun parse(code: String): CommandArea {
23
+ return when (code) {
24
+ "backup" -> BackupApplet
25
+ "master" -> PrimarySafety
26
+ else -> None
27
+ }
28
+ }
29
+ }
30
+ }
31
+
32
+ enum class CommandType(val code: String) {
33
+ SELECT_BACKUP_APPLET("select_backup_applet"),
34
+ SELECT_PRIMARY_SAFETY("select_primary_safety"),
35
+ GET_BACKUP_STATUS("get_backup_status"),
36
+ GET_PIN_STATUS("get_pin_status"),
37
+ GET_SERIAL_NUMBER("get_serial_number"),
38
+ GET_PIN_RETRY_COUNT("get_pin_retry_count"),
39
+ RESET_CARD("reset_card"),
40
+ VERIFY_PIN("verify_pin"),
41
+ SETUP_NEW_PIN("setup_new_pin"),
42
+ CHANGE_PIN("change_pin"),
43
+ BACKUP_DATA("backup_data"),
44
+ EXPORT_DATA("export_data"),
45
+ VERIFY_CERTIFICATE("verify_certificate"),
46
+ VERIFY_AUTH_DATA("verify_auth_data"),
47
+ }
48
+
49
+ class Command(
50
+ private val cardType: AppleCardType,
51
+ val area: CommandArea,
52
+ val command: String,
53
+ private val ignoreSafeChannel: Boolean,
54
+ private val useSafeChannel: Boolean,
55
+ private val useSafeChannelWhenOpen: Boolean,
56
+ private val hasOpenSafeChannel: Boolean,
57
+ val data: String,
58
+ ) {
59
+ private fun beforeConnecting(connection: Connection) {
60
+ val needOpenSafeChannel = useSafeChannel || (useSafeChannelWhenOpen && hasOpenSafeChannel)
61
+ val needCloseSafeChannel =
62
+ (!useSafeChannel && !(useSafeChannelWhenOpen && hasOpenSafeChannel))
63
+
64
+ if (!ignoreSafeChannel && needCloseSafeChannel) {
65
+ if (hasOpenSafeChannel) connection.resetSecureChannel()
66
+ }
67
+
68
+ if (area == CommandArea.BackupApplet) {
69
+ if (connection.getCurrentCommandArea() != CommandArea.BackupApplet) {
70
+ connection.selectBackupApplet(cardType)
71
+ }
72
+ } else if (area == CommandArea.PrimarySafety) {
73
+ if (connection.getCurrentCommandArea() != CommandArea.PrimarySafety) {
74
+ connection.selectPrimarySafety()
75
+ }
76
+ }
77
+
78
+ if (!ignoreSafeChannel && needOpenSafeChannel) {
79
+ val res = connection.openSafeChannel()
80
+ if (!res) throw NFCExceptions.InterruptException()
81
+ }
82
+ }
83
+
84
+ private fun splitHex(hex: String): List<String> {
85
+ val result = mutableListOf<String>()
86
+ for (i in hex.indices step 2) {
87
+ result.add(hex.substring(i, i + 2))
88
+ }
89
+ return result
90
+ }
91
+
92
+ private fun buildApdu(): String {
93
+ val commandByteArray = splitHex(command).map { it.toLong(16) }.toLongArray()
94
+ return GPCAPDUGenerator.buildGPCAPDU(
95
+ APDUParam(commandByteArray, data),
96
+ useSafeChannel || (useSafeChannelWhenOpen && hasOpenSafeChannel)
97
+ )
98
+ }
99
+
100
+ private fun parseResponse(response: String): String {
101
+ return if (useSafeChannel || (useSafeChannelWhenOpen && hasOpenSafeChannel)) {
102
+ nativeGPCParseSafeAPDUResponse(response)
103
+ } else {
104
+ nativeGPCParseAPDUResponse(response)
105
+ }
106
+ }
107
+
108
+ fun send(connection: Connection): SendResponse {
109
+ beforeConnecting(connection)
110
+ // buildApdu && parseResponse Use in pairs
111
+ val apdu = buildApdu()
112
+ val result = Connection.send(connection.isoDep, apdu)
113
+ val resultObject = CardResponse.objectFromData(parseResponse(result.rawResponse))
114
+ result.result = resultObject?.response ?: ""
115
+ return result
116
+ }
117
+ }
118
+
119
+ class CommandGenerator {
120
+ companion object {
121
+ private fun readConfig(): JsonObject {
122
+ val context = Utils.getApp()
123
+ val config = context.assets.open("config/command.json")
124
+ config.use {
125
+ val json = it.bufferedReader().use { it.readText() }
126
+ return JsonParser.parseString(json).asJsonObject
127
+ }
128
+ }
129
+
130
+ val instanceConfig by lazy(LazyThreadSafetyMode.NONE) {
131
+ readConfig()
132
+ }
133
+ }
134
+
135
+ fun generalCommand(
136
+ cardType: AppleCardType,
137
+ type: CommandType,
138
+ hasOpenSafeChannel: Boolean,
139
+ data: String? = null
140
+ ): Command {
141
+
142
+ val config = when (cardType) {
143
+ AppleCardType.V1 -> instanceConfig.getAsJsonObject(type.code).getAsJsonObject("v1")
144
+ AppleCardType.V2 -> instanceConfig.getAsJsonObject(type.code).getAsJsonObject("v2")
145
+ }
146
+
147
+ val area = if (config.has("area")) {
148
+ CommandArea.parse(config["area"].asString)
149
+ } else {
150
+ CommandArea.None
151
+ }
152
+ val ignoreSafeChannel =
153
+ config.has("ignoreSafeChannel") && config["ignoreSafeChannel"].asBoolean
154
+ val useSafeChannel = config.has("useSafeChannel") && config["useSafeChannel"].asBoolean
155
+ val useSafeChannelWhenOpen =
156
+ config.has("useSafeChannelWhenOpen") && config["useSafeChannelWhenOpen"].asBoolean
157
+ val needData = config.has("needData") && config["needData"].asBoolean
158
+ val command = if (config.has("command")) {
159
+ config["command"].asString
160
+ } else {
161
+ throw Exception("command not found")
162
+ }
163
+
164
+ if (needData && data == null) throw Exception("data is null")
165
+
166
+ return Command(
167
+ cardType = cardType,
168
+ area = area,
169
+ command = command,
170
+ ignoreSafeChannel = ignoreSafeChannel,
171
+ useSafeChannel = useSafeChannel,
172
+ useSafeChannelWhenOpen = useSafeChannelWhenOpen,
173
+ hasOpenSafeChannel = hasOpenSafeChannel,
174
+ data = data ?: ""
175
+ )
176
+ }
177
+
178
+ }
@@ -0,0 +1,439 @@
1
+ package so.onekey.app.wallet.lite.onekeyLite.nfc
2
+
3
+ import android.nfc.TagLostException
4
+ import android.nfc.tech.IsoDep
5
+ import org.haobtc.onekey.card.gpchannel.GPChannelNatives
6
+ import org.haobtc.onekey.card.gpchannel.GPChannelNatives.nativeGPCFinalize
7
+ import so.onekey.app.wallet.lite.keys.KeysNativeProvider
8
+ import so.onekey.app.wallet.lite.nfc.NFCExceptions
9
+ import so.onekey.app.wallet.lite.onekeyLite.NfcConstant
10
+ import so.onekey.app.wallet.lite.onekeyLite.entitys.*
11
+ import so.onekey.app.wallet.lite.onekeyLite.nfc.GPCAPDUGenerator.buildGPCAPDU
12
+ import so.onekey.app.wallet.lite.onekeyLite.nfc.GPCAPDUGenerator.combCommand
13
+ import so.onekey.app.wallet.lite.utils.HexUtils
14
+ import so.onekey.app.wallet.lite.utils.HexUtils.byteArr2HexStr
15
+ import so.onekey.app.wallet.lite.utils.HexUtils.hexString2Bytes
16
+ import so.onekey.app.wallet.lite.utils.LogUtil.printLog
17
+ import so.onekey.app.wallet.lite.utils.Utils
18
+ import java.io.IOException
19
+
20
+ class Connection(val isoDep: IsoDep, private val mCommandGenerator: CommandGenerator) {
21
+ companion object {
22
+ private const val TAG = "Connection"
23
+
24
+ @JvmStatic
25
+ private fun connect(isoDep: IsoDep?) {
26
+ val isConnected: Boolean = try {
27
+ isoDep?.isConnected ?: false
28
+ } catch (e: Exception) {
29
+ false
30
+ }
31
+ if (isConnected == false) {
32
+ isoDep?.connect()
33
+ isoDep?.timeout = 15000
34
+ }
35
+ }
36
+
37
+ @JvmStatic
38
+ fun send(isoDep: IsoDep, request: String?): SendResponse {
39
+ try {
40
+ connect(isoDep)
41
+ val response = isoDep.transceive(hexString2Bytes(request)) ?: byteArrayOf(
42
+ 0xFF.toByte(), 0xFF.toByte()
43
+ )
44
+ val resp: ByteArray = if (response.size > 2) {
45
+ response.copyOfRange(0, response.size - 2)
46
+ } else byteArrayOf()
47
+ val sw1 = response[response.size - 2]
48
+ val sw2 = response[response.size - 1]
49
+
50
+ return SendResponse(byteArr2HexStr(response), sw1, sw2, byteArr2HexStr(resp))
51
+ } catch (e: TagLostException) {
52
+ // throw NFCExceptions.InterruptException()
53
+ return SendResponse("0xFFFF", 0xFF.toByte(), 0xFF.toByte())
54
+ } catch (e: IOException) {
55
+ // e.printStackTrace()
56
+ return SendResponse("0xFFFF", 0xFF.toByte(), 0xFF.toByte())
57
+ }
58
+ }
59
+ }
60
+
61
+ private var mCardType: AppleCardType = AppleCardType.V2
62
+ private var mCardSerialNumber: String = NfcConstant.NOT_MATCH_DEVICE
63
+ private var hasOpenSafeChannel: Boolean = false
64
+ private var hasSetupPin: Boolean = false
65
+ private var hasBackup: Boolean = false
66
+ private var mCommandArea = CommandArea.None
67
+
68
+ init {
69
+ readCardInfo()
70
+ }
71
+
72
+ fun getCardType(): AppleCardType {
73
+ return mCardType
74
+ }
75
+
76
+ fun getCurrentCommandArea(): CommandArea {
77
+ return mCommandArea
78
+ }
79
+
80
+ fun selectPrimarySafety(): Boolean {
81
+ printLog(TAG, "---> selectPrimarySafety begin")
82
+ val command = mCommandGenerator.generalCommand(
83
+ mCardType, CommandType.SELECT_PRIMARY_SAFETY, hasOpenSafeChannel,
84
+ )
85
+ val res = command.send(this)
86
+ printLog(
87
+ TAG, "<--- selectPrimarySafety end: ${res.getCode()} ${res.data} area:${mCommandArea}"
88
+ )
89
+
90
+ if (res.isSuccess() && !res.isEmptyData()) {
91
+ mCommandArea = CommandArea.PrimarySafety
92
+ return true
93
+ }
94
+ return false
95
+ }
96
+
97
+ fun selectBackupApplet(cardType: AppleCardType?): Boolean {
98
+ printLog(TAG, "---> selectApplet begin")
99
+ val command = mCommandGenerator.generalCommand(
100
+ cardType ?: mCardType,
101
+ CommandType.SELECT_BACKUP_APPLET,
102
+ hasOpenSafeChannel,
103
+ cardType?.aid ?: mCardType.aid
104
+ )
105
+ val res = command.send(this)
106
+
107
+ printLog(TAG, "<--- selectApplet end: ${res.getCode()} ${res.data} area:${mCommandArea}")
108
+
109
+ if (res.isSuccess()) {
110
+ mCommandArea = CommandArea.BackupApplet
111
+ return true
112
+ }
113
+ return false
114
+ }
115
+
116
+ private fun getDeviceCertificate(): ParsedCertInfo? {
117
+ printLog(TAG, "---> getDeviceCertificate begin")
118
+ // #1.NFC:GET CERT.SD.ECKA 获取智能卡证书
119
+ val apdu = buildGPCAPDU(APDUParam(0x80, 0xCA, 0xBF, 0x21, "A60483021518"))
120
+ val rawCert = send(isoDep, apdu)
121
+ printLog(
122
+ TAG,
123
+ "<--- getDeviceCertificate end: ${rawCert.getCode()} ${rawCert.data} area:${mCommandArea}"
124
+ )
125
+
126
+ val cert = GPChannelNatives.nativeGPCTLVDecode(rawCert.data)
127
+ val certificate = CardResponse.objectFromData(cert).response
128
+
129
+ val certInfo = GPChannelNatives.nativeGPCParseCertificate(certificate)
130
+ return ParsedCertInfo.objectFromData(certInfo)
131
+ }
132
+
133
+ fun openSafeChannel(): Boolean {
134
+ printLog(TAG, "---> openSafeChannel begin")
135
+
136
+ if (hasOpenSafeChannel) {
137
+ printLog(TAG, "<--- has open safe channel")
138
+ return true
139
+ }
140
+
141
+ printLog(TAG, "0. ---> getDeviceCertificate begin")
142
+ val certInfo = getDeviceCertificate() ?: return false
143
+ printLog(TAG, "0. <--- getDeviceCertificate end: ${certInfo.subjectID}")
144
+
145
+ printLog(TAG, "1. ---> nativeGPCInitialize begin")
146
+ val param = SecureChanelParam.objectFromData(
147
+ KeysNativeProvider().getLiteSecureChannelInitParams(Utils.getApp())
148
+ )
149
+ param.cardGroupID = certInfo.subjectID
150
+ printLog(TAG, "nativeGPCInitialize read param done")
151
+ val initializeStatus = GPChannelNatives.nativeGPCInitialize(param.toString())
152
+ if (initializeStatus != 0) {
153
+ return false
154
+ }
155
+ printLog(TAG, "1. <--- nativeGPCInitialize end")
156
+
157
+ printLog(TAG, "2. ---> Perform security operation begin")
158
+ val command = mCommandGenerator.generalCommand(
159
+ mCardType, CommandType.VERIFY_CERTIFICATE, hasOpenSafeChannel, param.crt
160
+ )
161
+ val securityRes = command.send(this)
162
+ printLog(
163
+ TAG,
164
+ "2. <--- Perform security operation end: ${securityRes.getCode()} ${securityRes.data}"
165
+ )
166
+ if (!securityRes.isSuccess()) {
167
+ return false
168
+ }
169
+
170
+ printLog(TAG, "3. ---> mutual authenticate begin")
171
+ val authData = GPChannelNatives.nativeGPCBuildMutualAuthData()
172
+ printLog(TAG, "mutual authenticate data")
173
+ val authCommand = mCommandGenerator.generalCommand(
174
+ mCardType, CommandType.VERIFY_AUTH_DATA, hasOpenSafeChannel, authData
175
+ )
176
+ val authRes = authCommand.send(this)
177
+ printLog(TAG, "3. <--- mutual authenticate end")
178
+ if (authRes.isEmptyData() || !authRes.isSuccess()) {
179
+ return false
180
+ }
181
+
182
+ printLog(TAG, "4. ---> open secure channel begin")
183
+ val openStatus = GPChannelNatives.nativeGPCOpenSecureChannel(authRes.result)
184
+ if (openStatus != 0) {
185
+ return false
186
+ }
187
+ printLog(TAG, "4. <--- open secure channel end")
188
+
189
+ printLog(TAG, "<--- openSafeChannel end: Open Secure Channel OK")
190
+
191
+ hasOpenSafeChannel = true
192
+ return true
193
+ }
194
+
195
+ fun resetSecureChannel(): Boolean {
196
+ printLog(TAG, "---> resetSecureChannel begin")
197
+ nativeGPCFinalize()
198
+ hasOpenSafeChannel = false
199
+ printLog(TAG, "<--- resetSecureChannel end")
200
+ return true
201
+ }
202
+
203
+ private fun loadBackupStatus(): Boolean {
204
+ printLog(TAG, "---> getBackupStatus begin")
205
+ val command = mCommandGenerator.generalCommand(
206
+ mCardType, CommandType.GET_BACKUP_STATUS, hasOpenSafeChannel
207
+ )
208
+ val res = command.send(this)
209
+ printLog(TAG, "<--- getBackupStatus end: ${res.getCode()} ${res.data} area:${mCommandArea}")
210
+
211
+ if (!res.isSuccess()) {
212
+ return false
213
+ }
214
+
215
+ return (res.data == "02").also { hasBackup = it }
216
+ }
217
+
218
+ private fun loadPinStatus(): Boolean {
219
+ printLog(TAG, "---> getPinStatus begin")
220
+ val command = mCommandGenerator.generalCommand(
221
+ mCardType, CommandType.GET_PIN_STATUS, hasOpenSafeChannel, "DFFF028105"
222
+ )
223
+ val res = command.send(this)
224
+ printLog(TAG, "<--- getPinStatus end: ${res.getCode()} ${res.data} area:${mCommandArea}")
225
+
226
+ if (!res.isSuccess()) {
227
+ return false
228
+ }
229
+
230
+ val notSetPin = res.data == "02"
231
+ hasSetupPin = !notSetPin
232
+ return notSetPin
233
+ }
234
+
235
+ private fun loadSerialNumber(cardType: AppleCardType? = null): String {
236
+ printLog(TAG, "---> getSerialNumber begin")
237
+ val command = mCommandGenerator.generalCommand(
238
+ cardType ?: mCardType, CommandType.GET_SERIAL_NUMBER, hasOpenSafeChannel, "DFFF028101"
239
+ )
240
+ val res = command.send(this)
241
+
242
+ printLog(TAG, "<--- getSerialNumber end: ${res.getCode()} ${res.data} area:${mCommandArea}")
243
+ if (!res.isSuccess()) {
244
+ return NfcConstant.NOT_MATCH_DEVICE
245
+ }
246
+
247
+ return String(hexString2Bytes(res.data)).also {
248
+ mCardSerialNumber = it
249
+ }
250
+ }
251
+
252
+ private fun getRetryCount(): Int {
253
+ printLog(TAG, "---> getRetryNum begin")
254
+ val command = mCommandGenerator.generalCommand(
255
+ mCardType, CommandType.GET_PIN_RETRY_COUNT, hasOpenSafeChannel, "DFFF028102"
256
+ )
257
+ val res = command.send(this)
258
+
259
+ printLog(TAG, "<--- getRetryNum end: ${res.getCode()} ${res.data} area:${mCommandArea}")
260
+
261
+ if (res.isEmptyData() || !res.isSuccess()) {
262
+ return NfcConstant.GET_RETRY_NUM_INTERRUPT_STATUS
263
+ }
264
+ return res.data?.toInt(16) ?: NfcConstant.GET_RETRY_NUM_INTERRUPT_STATUS
265
+ }
266
+
267
+ private fun readCardInfo() {
268
+ printLog(TAG, "---> initCard begin")
269
+ try {
270
+ val cardTypes = arrayOf(AppleCardType.V1, AppleCardType.V2)
271
+ for (cardType in cardTypes) {
272
+ printLog(TAG, "---->> selectApplet: $cardType")
273
+ val serialNumber = loadSerialNumber(cardType)
274
+ if (serialNumber.startsWith(cardType.prefixSN)) {
275
+ mCardType = cardType
276
+ break
277
+ }
278
+ }
279
+ } catch (e: NFCExceptions) {
280
+ printLog(TAG, " init_channel NFCExceptions-->$e")
281
+ }
282
+
283
+ loadPinStatus()
284
+ if (mCardType == AppleCardType.V2) {
285
+ loadBackupStatus()
286
+ } else {
287
+ hasBackup = hasSetupPin
288
+ }
289
+ printLog(TAG, "<--- initCard end")
290
+ }
291
+
292
+ fun getCardInfo(): CardState {
293
+ val retryCount = getRetryCount()
294
+ return CardState(hasBackup, !hasSetupPin, mCardSerialNumber, retryCount)
295
+ }
296
+
297
+ fun getSerialNumber() = mCardSerialNumber
298
+
299
+ fun setupNewPin(pin: String): Boolean {
300
+ printLog(TAG, "---> setupNewPin begin")
301
+ val pinHex = HexUtils.stringToHexString(pin)
302
+ val command = mCommandGenerator.generalCommand(
303
+ mCardType, CommandType.SETUP_NEW_PIN, hasOpenSafeChannel, "DFFE0B8204080006$pinHex"
304
+ )
305
+ val res = command.send(this)
306
+ printLog(TAG, "<--- setupNewPin end: ${res.getCode()} ${res.data} area:${mCommandArea}")
307
+
308
+ if (!res.isSuccess()) {
309
+ return false
310
+ }
311
+
312
+ return true
313
+ }
314
+
315
+ fun changePin(oldPin: String, newPin: String?): Int {
316
+ printLog(TAG, "---> changePin begin")
317
+ val oldPinHex = HexUtils.stringToHexString(oldPin)
318
+ val newPinHex = HexUtils.stringToHexString(newPin)
319
+ val changePinCommand = combCommand(
320
+ hexString2Bytes("8204"), hexString2Bytes(oldPinHex), hexString2Bytes(newPinHex)
321
+ )
322
+ val execCommand = combCommand(hexString2Bytes("DFFE"), changePinCommand)
323
+
324
+ val command = mCommandGenerator.generalCommand(
325
+ mCardType, CommandType.CHANGE_PIN, hasOpenSafeChannel, byteArr2HexStr(execCommand)
326
+ )
327
+ val res = command.send(this)
328
+
329
+ printLog(TAG, "<--- changePin end: ${res.getCode()} ${res.data} area:${mCommandArea}")
330
+
331
+ return if (res.isConnectFailure()) {
332
+ NfcConstant.INTERRUPT_STATUS
333
+ } else if (res.isSuccess()) {
334
+ printLog(TAG, "--- verify success")
335
+ NfcConstant.CHANGE_PIN_SUCCESS
336
+ } else if (res.getCode() == "9B01") {
337
+ // V1 Lite Pin error
338
+ printLog(TAG, "--- verify error")
339
+ retryNumCommandAndReset()
340
+ } else if (res.getCode() == "6983") {
341
+ // V2 Lite Locked
342
+ printLog(TAG, "--- verify Too many errors, Locked")
343
+ resetCard()
344
+ } else {
345
+ if (res.getCode().startsWith("63C")) {
346
+ return res.sw2.toInt() and 0x0F
347
+ }
348
+ retryNumCommandAndReset()
349
+ }
350
+ }
351
+
352
+ fun startVerifyPin(pin: String): Int {
353
+ printLog(TAG, "---> startVerifyPin begin")
354
+ val pinHex = HexUtils.stringToHexString(pin)
355
+ val command = mCommandGenerator.generalCommand(
356
+ mCardType, CommandType.VERIFY_PIN, hasOpenSafeChannel, "06$pinHex"
357
+ )
358
+ val res = command.send(this)
359
+ printLog(TAG, "<--- startVerifyPin end: ${res.getCode()} ${res.data} area:${mCommandArea}")
360
+
361
+ return if (res.isConnectFailure()) {
362
+ NfcConstant.INTERRUPT_STATUS
363
+ } else if (res.isSuccess()) {
364
+ printLog(TAG, "--- verify success")
365
+ NfcConstant.VERIFY_SUCCESS
366
+ } else if (res.getCode() == "9B01") {
367
+ // V1 Lite Pin error
368
+ printLog(TAG, "--- verify error")
369
+ retryNumCommandAndReset()
370
+ } else if (res.getCode() == "6983") {
371
+ // V2 Lite Locked
372
+ printLog(TAG, "--- verify Too many errors, Locked")
373
+ resetCard()
374
+ } else {
375
+ if (res.getCode().startsWith("63C")) {
376
+ return res.sw2.toInt() and 0x0F
377
+ }
378
+ retryNumCommandAndReset()
379
+ }
380
+ }
381
+
382
+ fun backupData(mnemonic: String): Boolean {
383
+ printLog(TAG, "---> backupData begin")
384
+ val command = mCommandGenerator.generalCommand(
385
+ mCardType, CommandType.BACKUP_DATA, hasOpenSafeChannel, mnemonic
386
+ )
387
+ val res = command.send(this)
388
+ printLog(TAG, "<--- backupData end: ${res.getCode()} ${res.data} area:${mCommandArea}")
389
+
390
+ if (!res.isSuccess()) {
391
+ return false
392
+ }
393
+
394
+ return true
395
+ }
396
+
397
+ fun exportData(): String? {
398
+ printLog(TAG, "---> exportData begin")
399
+ val command = mCommandGenerator.generalCommand(
400
+ mCardType, CommandType.EXPORT_DATA, hasOpenSafeChannel
401
+ )
402
+ val res = command.send(this)
403
+ printLog(
404
+ TAG,
405
+ "<--- exportData end: ${res.getCode()} emptyData:${res.isEmptyData()} area:${mCommandArea}"
406
+ )
407
+
408
+ if (res.isEmptyData() || !res.isSuccess()) {
409
+ return null
410
+ }
411
+
412
+ return res.result
413
+ }
414
+
415
+ private fun retryNumCommandAndReset(): Int {
416
+ val leftRetryNum = getRetryCount()
417
+ return if (leftRetryNum == 0) {
418
+ resetCard()
419
+ } else {
420
+ leftRetryNum
421
+ }
422
+ }
423
+
424
+ fun resetCard(): Int {
425
+ printLog(TAG, "---> resetCard begin")
426
+ val command = mCommandGenerator.generalCommand(
427
+ mCardType, CommandType.RESET_CARD, hasOpenSafeChannel, "DFFE028205"
428
+ )
429
+ val res = command.send(this)
430
+
431
+ printLog(TAG, "<--- resetCard end: ${res.getCode()} ${res.data} area:${mCommandArea}")
432
+
433
+ return if (res.isConnectFailure()) {
434
+ NfcConstant.RESET_INTERRUPT_STATUS
435
+ } else {
436
+ NfcConstant.RESET_PIN_SUCCESS
437
+ }
438
+ }
439
+ }
@@ -0,0 +1,56 @@
1
+ package so.onekey.app.wallet.lite.onekeyLite.nfc
2
+
3
+ import com.google.gson.Gson
4
+ import org.haobtc.onekey.card.gpchannel.GPChannelNatives
5
+ import so.onekey.app.wallet.lite.onekeyLite.entitys.APDUParam
6
+ import so.onekey.app.wallet.lite.utils.LogUtil.printLog
7
+
8
+ object GPCAPDUGenerator {
9
+ private const val TAG = "GPCAPDUGenerator"
10
+
11
+ @JvmStatic
12
+ fun buildGPCAPDU(param: APDUParam, safeChannel: Boolean = false): String {
13
+ printLog(TAG, " --->> BuildGPCAPDU begin")
14
+ return if (safeChannel) {
15
+ GPChannelNatives.nativeGPCBuildSafeAPDU(
16
+ param.cla,
17
+ param.ins,
18
+ param.p1,
19
+ param.p2,
20
+ param.data
21
+ )
22
+ } else {
23
+ GPChannelNatives.nativeGPCBuildAPDU(
24
+ param.cla,
25
+ param.ins,
26
+ param.p1,
27
+ param.p2,
28
+ param.data
29
+ )
30
+ }.also {
31
+ printLog(TAG, " <<--- BuildGPCAPDU done: safeChannel:$safeChannel")
32
+ }
33
+ }
34
+
35
+ @JvmStatic
36
+ fun combCommand(command: ByteArray? = null, vararg params: ByteArray?): ByteArray {
37
+ var combParam = byteArrayOf()
38
+ params.forEach { param ->
39
+ param?.let {
40
+ combParam = combParam.plus(it.size.toByte())
41
+ combParam = combParam.plus(it)
42
+ }
43
+ }
44
+
45
+ var combCommand = byteArrayOf()
46
+ command?.let {
47
+ combCommand = combCommand.plus(it)
48
+ if (params.size != 1) {
49
+ // params 只有一个的时候就不再次拼接长度了
50
+ combCommand = combCommand.plus(combParam.size.toByte())
51
+ }
52
+ }
53
+ combCommand = combCommand.plus(combParam)
54
+ return combCommand
55
+ }
56
+ }
@@ -0,0 +1,14 @@
1
+ package so.onekey.app.wallet.lite.utils
2
+
3
+ import com.facebook.react.bridge.ReactContext
4
+ import com.facebook.react.modules.core.DeviceEventManagerModule
5
+
6
+ fun sendEvent(
7
+ reactContext: ReactContext,
8
+ eventName: String,
9
+ params: String? = null
10
+ ) {
11
+ reactContext
12
+ .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
13
+ .emit(eventName, params)
14
+ }