diff --git a/app-common/src/main/java/im/angry/openeuicc/core/OmapiApduInterface.kt b/app-common/src/main/java/im/angry/openeuicc/core/OmapiApduInterface.kt index c7fed90..0a1a0be 100644 --- a/app-common/src/main/java/im/angry/openeuicc/core/OmapiApduInterface.kt +++ b/app-common/src/main/java/im/angry/openeuicc/core/OmapiApduInterface.kt @@ -40,20 +40,24 @@ class OmapiApduInterface( override fun logicalChannelOpen(aid: ByteArray): Int { val channel = session.openLogicalChannel(aid)!! - val id = index.getAndAdd(1) + val id = index.addAndGet(1) channels[id] = channel return id } override fun logicalChannelClose(handle: Int) { val channel = channels[handle] - check(channel != null) { "Channel $handle does not exist" } + check(channel != null) { + "Invalid logical channel handle $handle" + } channel.close() } override fun transmit(handle: Int, tx: ByteArray): ByteArray { val channel = channels[handle] - check(channel != null) { "Channel $handle does not exist" } + check(channel != null) { + "Invalid logical channel handle $handle" + } if (runBlocking { verboseLoggingFlow.first() }) { Log.d(TAG, "OMAPI APDU: ${tx.encodeHex()}") 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 2a01c9e..f9e764b 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 @@ -23,6 +23,11 @@ class UsbApduInterface( override var atr: ByteArray? = null + override val valid: Boolean + get() = channels.isNotEmpty() + + private var channels = mutableSetOf() + override fun connect() { ccidDescription = UsbCcidDescription.fromRawDescriptors(conn.rawDescriptors)!! @@ -76,10 +81,15 @@ class UsbApduInterface( return -1 } + channels.add(channelId) + return channelId } override fun logicalChannelClose(handle: Int) { + check(channels.contains(handle)) { + "Invalid logical channel handle $handle" + } // CLOSE LOGICAL CHANNEL val req = manageChannelCmd(false, handle.toByte()) val resp = transmitApduByChannel(req, handle.toByte()) @@ -87,15 +97,16 @@ class UsbApduInterface( if (!isSuccessResponse(resp)) { Log.d(TAG, "CLOSE LOGICAL CHANNEL failed: ${resp.encodeHex()}") } + channels.remove(handle) } override fun transmit(handle: Int, tx: ByteArray): ByteArray { + check(channels.contains(handle)) { + "Invalid logical channel handle $handle" + } return transmitApduByChannel(tx, handle.toByte()) } - override val valid: Boolean - get() = atr != null - private fun isSuccessResponse(resp: ByteArray): Boolean = resp.size >= 2 && resp[resp.size - 2] == 0x90.toByte() && resp[resp.size - 1] == 0x00.toByte() diff --git a/app/src/main/java/im/angry/openeuicc/core/TelephonyManagerApduInterface.kt b/app/src/main/java/im/angry/openeuicc/core/TelephonyManagerApduInterface.kt index b7a9482..f0b1909 100644 --- a/app/src/main/java/im/angry/openeuicc/core/TelephonyManagerApduInterface.kt +++ b/app/src/main/java/im/angry/openeuicc/core/TelephonyManagerApduInterface.kt @@ -18,7 +18,10 @@ class TelephonyManagerApduInterface( const val TAG = "TelephonyManagerApduInterface" } - override var valid: Boolean = false + override val valid: Boolean + get() = channels.isNotEmpty() + + private var channels = mutableSetOf() override fun connect() { // Do nothing @@ -32,35 +35,31 @@ class TelephonyManagerApduInterface( val hex = aid.encodeHex() val channel = tm.iccOpenLogicalChannelByPortCompat(port.card.physicalSlotIndex, port.portIndex, hex, 0) if (channel.status != IccOpenLogicalChannelResponse.STATUS_NO_ERROR || channel.channel == IccOpenLogicalChannelResponse.INVALID_CHANNEL) { - throw IllegalArgumentException("Cannot open logical channel $hex via TelephonManager on slot ${port.card.physicalSlotIndex} port ${port.portIndex}") + throw IllegalArgumentException("Cannot open logical channel $hex via TelephonyManager on slot ${port.card.physicalSlotIndex} port ${port.portIndex}") } - valid = true + channels.add(channel.channel) return channel.channel } override fun logicalChannelClose(handle: Int) { + check(channels.contains(handle)) { + "Invalid logical channel handle $handle" + } tm.iccCloseLogicalChannelByPortCompat(port.card.physicalSlotIndex, port.portIndex, handle) - valid = false + channels.remove(handle) } override fun transmit(handle: Int, tx: ByteArray): ByteArray { + check(channels.contains(handle)) { + "Invalid logical channel handle $handle" + } if (runBlocking { verboseLoggingFlow.first() }) { Log.d(TAG, "TelephonyManager APDU: ${tx.encodeHex()}") } - - val cla = tx[0].toUByte().toInt() - val ins = tx[1].toUByte().toInt() - val p1 = tx[2].toUByte().toInt() - val p2 = tx[3].toUByte().toInt() - val p3 = tx[4].toUByte().toInt() - val p4 = tx.drop(5).toByteArray().encodeHex() - - // @formatter:off val result = tm.iccTransmitApduLogicalChannelByPortCompat( port.card.physicalSlotIndex, port.portIndex, handle, - cla, ins, p1, p2, p3, p4 + tx, ) - // @formatter:on if (runBlocking { verboseLoggingFlow.first() }) Log.d(TAG, "TelephonyManager APDU response: $result") return result?.decodeHex() ?: byteArrayOf() diff --git a/app/src/main/java/im/angry/openeuicc/util/PrivilegedTelephonyCompat.kt b/app/src/main/java/im/angry/openeuicc/util/PrivilegedTelephonyCompat.kt index dbd39f2..a9df18e 100644 --- a/app/src/main/java/im/angry/openeuicc/util/PrivilegedTelephonyCompat.kt +++ b/app/src/main/java/im/angry/openeuicc/util/PrivilegedTelephonyCompat.kt @@ -111,15 +111,26 @@ fun TelephonyManager.iccCloseLogicalChannelByPortCompat( } fun TelephonyManager.iccTransmitApduLogicalChannelByPortCompat( - slotIndex: Int, portIndex: Int, channel: Int, - cla: Int, inst: Int, p1: Int, p2: Int, p3: Int, data: String? -): String? = - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + slotIndex: Int, + portIndex: Int, + channel: Int, + tx: ByteArray +): String? { + val cla = tx[0].toUByte().toInt() + val ins = tx[1].toUByte().toInt() + val p1 = tx[2].toUByte().toInt() + val p2 = tx[3].toUByte().toInt() + val p3 = tx[4].toUByte().toInt() + val p4 = tx.drop(5).toByteArray().encodeHex() + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { iccTransmitApduLogicalChannelByPort( - slotIndex, portIndex, channel, cla, inst, p1, p2, p3, data + slotIndex, portIndex, channel, + cla, ins, p1, p2, p3, p4 ) } else { iccTransmitApduLogicalChannelBySlot( - slotIndex, channel, cla, inst, p1, p2, p3, data + slotIndex, channel, + cla, ins, p1, p2, p3, p4 ) } +}