Compare commits

..

No commits in common. "576ede455d70bdfed0997ca655a1703178c7902c" and "41f16e03cf51bd0c04e934438ca809cf0d8535fa" have entirely different histories.

2 changed files with 43 additions and 57 deletions

View file

@ -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() channelId = resp[0].toInt()
Log.d(TAG, "channelId = $channelId") Log.d(TAG, "channelId = $channelId")
// Then, select AID // Then, select AID
val selectAid = selectByDfCmd(aid, channelId.toByte()) val selectAid = selectByDfCmd(aid, channelId.toByte())
Log.d(TAG, "Select DF command: ${selectAid.encodeHex()}")
val selectAidResp = transmitApduByChannel(selectAid, channelId.toByte()) val selectAidResp = transmitApduByChannel(selectAid, channelId.toByte())
Log.d(TAG, "Select DF resp: ${selectAidResp.encodeHex()}")
if (!isSuccessResponse(selectAidResp)) { channelId
Log.d(TAG, "Select DF failed : ${selectAidResp.encodeHex()}") } else {
return -1 -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,21 +131,15 @@ 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 sw1 = resp[resp.size - 2].toInt() and 0xFF
var sw2 = resp[resp.size - 1].toInt() and 0xFF var sw2 = resp[resp.size - 1].toInt() and 0xFF
if (sw1 == 0x6C) { if (sw1 == 0x6C) {
// 0x6C = wrong le
// so we fix the le field here
realTx[realTx.size - 1] = resp[resp.size - 1] realTx[realTx.size - 1] = resp[resp.size - 1]
resp = transceiver.sendXfrBlock(realTx).data!! resp = transceiver.sendXfrBlock(realTx).data!!
} else if (sw1 == 0x61) { } else if (sw1 == 0x61) {
// 0x61 = X bytes available
// continue reading by GET RESPONSE
do { do {
// GET RESPONSE
val getResponseCmd = byteArrayOf( val getResponseCmd = byteArrayOf(
realTx[0], 0xC0.toByte(), 0x00, 0x00, sw2.toByte() realTx[0], 0xC0.toByte(), 0x00, 0x00, sw2.toByte()
) )
@ -159,6 +152,7 @@ class UsbApduInterface(
sw2 = resp[resp.size - 1].toInt() and 0xFF sw2 = resp[resp.size - 1].toInt() and 0xFF
} while (sw1 == 0x61) } while (sw1 == 0x61)
} }
}
return resp return resp
} }

View file

@ -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() {