Compare commits
No commits in common. "576ede455d70bdfed0997ca655a1703178c7902c" and "41f16e03cf51bd0c04e934438ca809cf0d8535fa" have entirely different histories.
576ede455d
...
41f16e03cf
2 changed files with 43 additions and 57 deletions
|
@ -46,6 +46,7 @@ class UsbApduInterface(
|
||||||
|
|
||||||
// OPEN LOGICAL CHANNEL
|
// OPEN LOGICAL CHANNEL
|
||||||
val req = manageChannelCmd(true, 0)
|
val req = manageChannelCmd(true, 0)
|
||||||
|
Log.d(TAG, "OPEN LOGICAL CHANNEL: ${req.encodeHex()}")
|
||||||
|
|
||||||
val resp = try {
|
val resp = try {
|
||||||
transmitApduByChannel(req, 0)
|
transmitApduByChannel(req, 0)
|
||||||
|
@ -53,25 +54,24 @@ class UsbApduInterface(
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
Log.d(TAG, "OPEN LOGICAL CHANNEL response: ${resp.encodeHex()}")
|
||||||
|
|
||||||
if (!isSuccessResponse(resp)) {
|
return if (resp.size >= 2 && resp.sliceArray((resp.size - 2) until resp.size).contentEquals(
|
||||||
Log.d(TAG, "OPEN LOGICAL CHANNEL failed: ${resp.encodeHex()}")
|
byteArrayOf(0x90.toByte(), 0x00)
|
||||||
return -1
|
)
|
||||||
|
) {
|
||||||
|
channelId = resp[0].toInt()
|
||||||
|
Log.d(TAG, "channelId = $channelId")
|
||||||
|
|
||||||
|
// Then, select AID
|
||||||
|
val selectAid = selectByDfCmd(aid, channelId.toByte())
|
||||||
|
Log.d(TAG, "Select DF command: ${selectAid.encodeHex()}")
|
||||||
|
val selectAidResp = transmitApduByChannel(selectAid, channelId.toByte())
|
||||||
|
Log.d(TAG, "Select DF resp: ${selectAidResp.encodeHex()}")
|
||||||
|
channelId
|
||||||
|
} else {
|
||||||
|
-1
|
||||||
}
|
}
|
||||||
|
|
||||||
channelId = resp[0].toInt()
|
|
||||||
Log.d(TAG, "channelId = $channelId")
|
|
||||||
|
|
||||||
// Then, select AID
|
|
||||||
val selectAid = selectByDfCmd(aid, channelId.toByte())
|
|
||||||
val selectAidResp = transmitApduByChannel(selectAid, channelId.toByte())
|
|
||||||
|
|
||||||
if (!isSuccessResponse(selectAidResp)) {
|
|
||||||
Log.d(TAG, "Select DF failed : ${selectAidResp.encodeHex()}")
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
return channelId
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun logicalChannelClose(handle: Int) {
|
override fun logicalChannelClose(handle: Int) {
|
||||||
|
@ -80,26 +80,25 @@ class UsbApduInterface(
|
||||||
|
|
||||||
// CLOSE LOGICAL CHANNEL
|
// CLOSE LOGICAL CHANNEL
|
||||||
val req = manageChannelCmd(false, channelId.toByte())
|
val req = manageChannelCmd(false, channelId.toByte())
|
||||||
val resp = transmitApduByChannel(req, channelId.toByte())
|
Log.d(TAG, "CLOSE LOGICAL CHANNEL: ${req.encodeHex()}")
|
||||||
|
|
||||||
if (!isSuccessResponse(resp)) {
|
val resp = transmitApduByChannel(req, channelId.toByte())
|
||||||
Log.d(TAG, "CLOSE LOGICAL CHANNEL failed: ${resp.encodeHex()}")
|
Log.d(TAG, "CLOSE LOGICAL CHANNEL response: ${resp.encodeHex()}")
|
||||||
}
|
|
||||||
|
|
||||||
channelId = -1
|
channelId = -1
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun transmit(tx: ByteArray): ByteArray {
|
override fun transmit(tx: ByteArray): ByteArray {
|
||||||
check(channelId != -1) { "Logical channel is not opened" }
|
check(channelId != -1) { "Logical channel is not opened" }
|
||||||
return transmitApduByChannel(tx, channelId.toByte())
|
Log.d(TAG, "USB APDU command: ${tx.encodeHex()}")
|
||||||
|
val resp = transmitApduByChannel(tx, channelId.toByte())
|
||||||
|
Log.d(TAG, "USB APDU response: ${resp.encodeHex()}")
|
||||||
|
return resp
|
||||||
}
|
}
|
||||||
|
|
||||||
override val valid: Boolean
|
override val valid: Boolean
|
||||||
get() = true
|
get() = true
|
||||||
|
|
||||||
private fun isSuccessResponse(resp: ByteArray): Boolean =
|
|
||||||
resp.size >= 2 && resp[resp.size - 2] == 0x90.toByte() && resp[resp.size - 1] == 0x00.toByte()
|
|
||||||
|
|
||||||
private fun buildCmd(cla: Byte, ins: Byte, p1: Byte, p2: Byte, data: ByteArray?, le: Byte?) =
|
private fun buildCmd(cla: Byte, ins: Byte, p1: Byte, p2: Byte, data: ByteArray?, le: Byte?) =
|
||||||
byteArrayOf(cla, ins, p1, p2).let {
|
byteArrayOf(cla, ins, p1, p2).let {
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
|
@ -132,32 +131,27 @@ class UsbApduInterface(
|
||||||
|
|
||||||
var resp = transceiver.sendXfrBlock(realTx).data!!
|
var resp = transceiver.sendXfrBlock(realTx).data!!
|
||||||
|
|
||||||
if (resp.size < 2) throw RuntimeException("APDU response smaller than 2 (sw1 + sw2)!")
|
if (resp.size >= 2) {
|
||||||
|
var sw1 = resp[resp.size - 2].toInt() and 0xFF
|
||||||
|
var sw2 = resp[resp.size - 1].toInt() and 0xFF
|
||||||
|
|
||||||
var sw1 = resp[resp.size - 2].toInt() and 0xFF
|
if (sw1 == 0x6C) {
|
||||||
var sw2 = resp[resp.size - 1].toInt() and 0xFF
|
realTx[realTx.size - 1] = resp[resp.size - 1]
|
||||||
|
resp = transceiver.sendXfrBlock(realTx).data!!
|
||||||
|
} else if (sw1 == 0x61) {
|
||||||
|
do {
|
||||||
|
val getResponseCmd = byteArrayOf(
|
||||||
|
realTx[0], 0xC0.toByte(), 0x00, 0x00, sw2.toByte()
|
||||||
|
)
|
||||||
|
|
||||||
if (sw1 == 0x6C) {
|
val tmp = transceiver.sendXfrBlock(getResponseCmd).data!!
|
||||||
// 0x6C = wrong le
|
|
||||||
// so we fix the le field here
|
|
||||||
realTx[realTx.size - 1] = resp[resp.size - 1]
|
|
||||||
resp = transceiver.sendXfrBlock(realTx).data!!
|
|
||||||
} else if (sw1 == 0x61) {
|
|
||||||
// 0x61 = X bytes available
|
|
||||||
// continue reading by GET RESPONSE
|
|
||||||
do {
|
|
||||||
// GET RESPONSE
|
|
||||||
val getResponseCmd = byteArrayOf(
|
|
||||||
realTx[0], 0xC0.toByte(), 0x00, 0x00, sw2.toByte()
|
|
||||||
)
|
|
||||||
|
|
||||||
val tmp = transceiver.sendXfrBlock(getResponseCmd).data!!
|
resp = resp.sliceArray(0 until (resp.size - 2)) + tmp
|
||||||
|
|
||||||
resp = resp.sliceArray(0 until (resp.size - 2)) + tmp
|
sw1 = resp[resp.size - 2].toInt() and 0xFF
|
||||||
|
sw2 = resp[resp.size - 1].toInt() and 0xFF
|
||||||
sw1 = resp[resp.size - 2].toInt() and 0xFF
|
} while (sw1 == 0x61)
|
||||||
sw2 = resp[resp.size - 1].toInt() and 0xFF
|
}
|
||||||
} while (sw1 == 0x61)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return resp
|
return resp
|
||||||
|
|
|
@ -116,20 +116,12 @@ class UsbCcidReaderFragment : Fragment(), OpenEuiccContextMarker {
|
||||||
|
|
||||||
override fun onDetach() {
|
override fun onDetach() {
|
||||||
super.onDetach()
|
super.onDetach()
|
||||||
try {
|
requireContext().unregisterReceiver(usbPermissionReceiver)
|
||||||
requireContext().unregisterReceiver(usbPermissionReceiver)
|
|
||||||
} catch (_: Exception) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
try {
|
requireContext().unregisterReceiver(usbPermissionReceiver)
|
||||||
requireContext().unregisterReceiver(usbPermissionReceiver)
|
|
||||||
} catch (_: Exception) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun tryLoadUsbChannel() {
|
private suspend fun tryLoadUsbChannel() {
|
||||||
|
|
Loading…
Add table
Reference in a new issue