From fc9f96206154465a2810e37674b21708228c8539 Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Mon, 1 Jul 2024 14:59:56 -0400 Subject: [PATCH] UsbApduInterface: cleanup --- .../openeuicc/core/usb/UsbApduInterface.kt | 88 ++++++++++--------- 1 file changed, 47 insertions(+), 41 deletions(-) diff --git a/app-common/src/main/java/im/angry/openeuicc/core/usb/UsbApduInterface.kt b/app-common/src/main/java/im/angry/openeuicc/core/usb/UsbApduInterface.kt index bc60817..98e738d 100644 --- a/app-common/src/main/java/im/angry/openeuicc/core/usb/UsbApduInterface.kt +++ b/app-common/src/main/java/im/angry/openeuicc/core/usb/UsbApduInterface.kt @@ -46,7 +46,6 @@ class UsbApduInterface( // OPEN LOGICAL CHANNEL val req = manageChannelCmd(true, 0) - Log.d(TAG, "OPEN LOGICAL CHANNEL: ${req.encodeHex()}") val resp = try { transmitApduByChannel(req, 0) @@ -54,24 +53,25 @@ class UsbApduInterface( e.printStackTrace() return -1 } - Log.d(TAG, "OPEN LOGICAL CHANNEL response: ${resp.encodeHex()}") - return if (resp.size >= 2 && resp.sliceArray((resp.size - 2) until resp.size).contentEquals( - byteArrayOf(0x90.toByte(), 0x00) - ) - ) { - 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 + if (!isSuccessResponse(resp)) { + Log.d(TAG, "OPEN LOGICAL CHANNEL failed: ${resp.encodeHex()}") + return -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) { @@ -80,25 +80,26 @@ class UsbApduInterface( // CLOSE LOGICAL CHANNEL val req = manageChannelCmd(false, channelId.toByte()) - Log.d(TAG, "CLOSE LOGICAL CHANNEL: ${req.encodeHex()}") - val resp = transmitApduByChannel(req, channelId.toByte()) - Log.d(TAG, "CLOSE LOGICAL CHANNEL response: ${resp.encodeHex()}") + + if (!isSuccessResponse(resp)) { + Log.d(TAG, "CLOSE LOGICAL CHANNEL failed: ${resp.encodeHex()}") + } channelId = -1 } override fun transmit(tx: ByteArray): ByteArray { check(channelId != -1) { "Logical channel is not opened" } - Log.d(TAG, "USB APDU command: ${tx.encodeHex()}") - val resp = transmitApduByChannel(tx, channelId.toByte()) - Log.d(TAG, "USB APDU response: ${resp.encodeHex()}") - return resp + return transmitApduByChannel(tx, channelId.toByte()) } override val valid: Boolean 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?) = byteArrayOf(cla, ins, p1, p2).let { if (data != null) { @@ -131,27 +132,32 @@ class UsbApduInterface( var resp = transceiver.sendXfrBlock(realTx).data!! - if (resp.size >= 2) { - var sw1 = resp[resp.size - 2].toInt() and 0xFF - var sw2 = resp[resp.size - 1].toInt() and 0xFF + if (resp.size < 2) throw RuntimeException("APDU response smaller than 2 (sw1 + sw2)!") - if (sw1 == 0x6C) { - 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() - ) + var sw1 = resp[resp.size - 2].toInt() and 0xFF + var sw2 = resp[resp.size - 1].toInt() and 0xFF - val tmp = transceiver.sendXfrBlock(getResponseCmd).data!! + if (sw1 == 0x6C) { + // 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() + ) - resp = resp.sliceArray(0 until (resp.size - 2)) + tmp + val tmp = transceiver.sendXfrBlock(getResponseCmd).data!! - sw1 = resp[resp.size - 2].toInt() and 0xFF - sw2 = resp[resp.size - 1].toInt() and 0xFF - } while (sw1 == 0x61) - } + 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 + } while (sw1 == 0x61) } return resp