From b3c7192d999f7a647c2c88effe933b5236732bba Mon Sep 17 00:00:00 2001 From: TwistedUmbrellaX Date: Sun, 10 Sep 2023 22:51:15 -0400 Subject: [PATCH] Due to detection restrictions, require NXP --- .../hiddenramblings/tagmo/nfctech/Infinity.kt | 49 +++++------------ .../tagmo/nfctech/NfcActivity.kt | 53 ++++++++++--------- .../hiddenramblings/tagmo/nfctech/ScanTag.kt | 2 - .../tagmo/nfctech/Skylanders.kt | 47 +++++----------- app/src/main/res/values/strings.xml | 2 + 5 files changed, 57 insertions(+), 96 deletions(-) diff --git a/app/src/main/java/com/hiddenramblings/tagmo/nfctech/Infinity.kt b/app/src/main/java/com/hiddenramblings/tagmo/nfctech/Infinity.kt index 7525a9da8..7949459d2 100644 --- a/app/src/main/java/com/hiddenramblings/tagmo/nfctech/Infinity.kt +++ b/app/src/main/java/com/hiddenramblings/tagmo/nfctech/Infinity.kt @@ -18,7 +18,7 @@ import java.io.IOException import java.math.BigInteger import java.security.MessageDigest -class Infinity : TagTechnology { +class Infinity(mifare: MifareClassic?) : TagTechnology { private val magicNumbers: Array = arrayOf( BigInteger("3"), BigInteger("5"), @@ -28,18 +28,9 @@ class Infinity : TagTechnology { ) private val tagMifare: MifareClassic? - private val tagNfcA: NfcA? private var maxTransceiveLength: Int = 0 - constructor(nfcA: NfcA?) { - tagNfcA = nfcA?.also { - maxTransceiveLength = it.maxTransceiveLength / 4 + 1 - } - tagMifare = null - } - - constructor(mifare: MifareClassic?) { - tagNfcA = null + init { tagMifare = mifare?.also { maxTransceiveLength = it.maxTransceiveLength / 4 + 1 } @@ -47,32 +38,27 @@ class Infinity : TagTechnology { @Suppress("unused") var timeout: Int - get() = tagMifare?.timeout ?: tagNfcA?.timeout ?: 0 + get() = tagMifare?.timeout ?: 0 set(timeout) { tagMifare?.timeout = timeout - tagNfcA?.timeout = timeout } @Throws(IOException::class) override fun connect() { - tagMifare?.connect() ?: tagNfcA?.connect() + tagMifare?.connect() } override fun isConnected(): Boolean { - return tagMifare?.isConnected ?: tagNfcA?.isConnected ?: false - } - - fun isClassic1K() : Boolean { - return (tagMifare?.size == MifareClassic.SIZE_1K) + return tagMifare?.isConnected ?: false } @Throws(IOException::class) override fun close() { - tagMifare?.close() ?: tagNfcA?.close() + tagMifare?.close() } override fun getTag(): Tag? { - return tagMifare?.tag ?: tagNfcA?.tag + return tagMifare?.tag } private fun keyInfinity(uid: String) : ByteArray { @@ -93,8 +79,11 @@ class Infinity : TagTechnology { ) } + @Throws(IOException::class) fun authenticate() { tagMifare?.let { + if (it.size != MifareClassic.SIZE_1K) + throw IOException(TagMo.appContext.getString(R.string.error_tag_format)) val keyA = keyInfinity(it.tag.id.toHex()) it.authenticateSectorWithKeyA(0, keyA) Debug.warn(Companion::class.java, keyA.toHex()) @@ -104,7 +93,7 @@ class Infinity : TagTechnology { fun transceive(data: ByteArray?): ByteArray? { return try { - tagMifare?.transceive(data) ?: tagNfcA?.transceive(data) + tagMifare?.transceive(data) } catch (e: IOException) { Debug.warn(e) null @@ -115,25 +104,13 @@ class Infinity : TagTechnology { private infix fun Short.equals(i: Int): Boolean = this == i.toShort() - private fun getMifareClasssic(tag: Tag?): Infinity? { - return MifareClassic.get(tag)?.let { Infinity(it) } - } - - private fun getNfcA(tag: Tag?): Infinity? { + operator fun get(tag: Tag?): Infinity? { return NfcA.get(tag)?.let { if (it.sak equals 0x09 && it.atqa.equals(byteArrayOf(0x00, 0x44))) - Infinity(it) + MifareClassic.get(tag)?.let { mifare -> Infinity(mifare) } else null } } - - operator fun get(tag: Tag?): Infinity? { - return try { - getMifareClasssic(tag)?.also { it.connect() } - } catch (e: IOException) { - getNfcA(tag)?.also { it.connect() } - } ?: getNfcA(tag)?.also { it.connect() } - } } } \ No newline at end of file diff --git a/app/src/main/java/com/hiddenramblings/tagmo/nfctech/NfcActivity.kt b/app/src/main/java/com/hiddenramblings/tagmo/nfctech/NfcActivity.kt index a8a833c63..b916a18d9 100644 --- a/app/src/main/java/com/hiddenramblings/tagmo/nfctech/NfcActivity.kt +++ b/app/src/main/java/com/hiddenramblings/tagmo/nfctech/NfcActivity.kt @@ -66,9 +66,9 @@ class NfcActivity : AppCompatActivity() { private var isEliteIntent = false private var isEliteDevice = false - private var infinity: Infinity? = null private var ntag215: NTAG215? = null private var skylanders: Skylanders? = null + private var infinity: Infinity? = null private var writeCount = 0 private var tagTech: String? = null private var hasTestedElite = false @@ -256,29 +256,6 @@ class NfcActivity : AppCompatActivity() { } } - private suspend fun onMifareClassic(tag: Tag?) = withContext(Dispatchers.IO) { - val command = intent - val mode = command.action - try { - skylanders = Skylanders[tag] - skylanders?.let { mifare -> - // mifare.connect() - mifare.authenticate() - } - } catch (e: Exception) { - Debug.warn(e) - Debug.getExceptionCause(e)?.let { error -> - - } ?: { - showError(getString(R.string.error_unknown)) - try { - Debug.processLogcat(this@NfcActivity) - } catch (ignored: IOException) { - } - } - } - } - private suspend fun onMifareUltralight(tag: Tag?) = withContext(Dispatchers.IO) { val command = intent val mode = command.action @@ -287,7 +264,6 @@ class NfcActivity : AppCompatActivity() { ntag215 = if (NFCIntent.ACTION_BLIND_SCAN == mode || isEliteIntent) NTAG215.getBlind(tag) else NTAG215[tag] ntag215?.let { mifare -> - // mifare.connect() if (!hasTestedElite) { hasTestedElite = true if (mifare.isPowerTag) { @@ -647,6 +623,33 @@ class NfcActivity : AppCompatActivity() { } } + private suspend fun onMifareClassic(tag: Tag?) = withContext(Dispatchers.IO) { + val command = intent + val mode = command.action + try { + skylanders = Skylanders[tag] + infinity = Infinity[tag] + skylanders?.let { mifare -> + mifare.authenticate() + } ?: infinity?.let { mifare -> + mifare.authenticate() + } ?: { + showError(getString(R.string.error_nxp_required)) + } + } catch (e: Exception) { + Debug.warn(e) + Debug.getExceptionCause(e)?.let { error -> + + } ?: { + showError(getString(R.string.error_unknown)) + try { + Debug.processLogcat(this@NfcActivity) + } catch (ignored: IOException) { + } + } + } + } + private suspend fun onTagDiscovered(intent: Intent) = withContext(Dispatchers.IO) { setResult(RESULT_CANCELED) val tag = intent.parcelable(NfcAdapter.EXTRA_TAG) diff --git a/app/src/main/java/com/hiddenramblings/tagmo/nfctech/ScanTag.kt b/app/src/main/java/com/hiddenramblings/tagmo/nfctech/ScanTag.kt index 7b0ec12e7..e34fe1ca5 100644 --- a/app/src/main/java/com/hiddenramblings/tagmo/nfctech/ScanTag.kt +++ b/app/src/main/java/com/hiddenramblings/tagmo/nfctech/ScanTag.kt @@ -9,7 +9,6 @@ import android.os.Bundle import androidx.appcompat.app.AlertDialog import com.google.android.material.snackbar.Snackbar import com.hiddenramblings.tagmo.BrowserActivity -import com.hiddenramblings.tagmo.BuildConfig import com.hiddenramblings.tagmo.NFCIntent import com.hiddenramblings.tagmo.Preferences import com.hiddenramblings.tagmo.R @@ -44,7 +43,6 @@ class ScanTag { try { mifare = NTAG215[tag] mifare?.let { ntag -> - // ntag.connect() if (!hasTestedElite) { hasTestedElite = true if (ntag.isPowerTag && prefs.eliteEnabled()) isEliteDevice = ntag.isElite diff --git a/app/src/main/java/com/hiddenramblings/tagmo/nfctech/Skylanders.kt b/app/src/main/java/com/hiddenramblings/tagmo/nfctech/Skylanders.kt index 49b633ea7..aab9c5eb0 100644 --- a/app/src/main/java/com/hiddenramblings/tagmo/nfctech/Skylanders.kt +++ b/app/src/main/java/com/hiddenramblings/tagmo/nfctech/Skylanders.kt @@ -17,23 +17,14 @@ import com.hiddenramblings.tagmo.nfctech.TagArray.toHexByteArray import java.io.IOException import java.math.BigInteger -class Skylanders : TagTechnology { +class Skylanders(mifare: MifareClassic?) : TagTechnology { private val magicNumbers = listOf(2, 3, 73, 1103, 2017, 560381651, 12868356821) private val tagMifare: MifareClassic? - private val tagNfcA: NfcA? private var maxTransceiveLength: Int = 0 - constructor(nfcA: NfcA?) { - tagNfcA = nfcA?.also { - maxTransceiveLength = it.maxTransceiveLength / 4 + 1 - } - tagMifare = null - } - - constructor(mifare: MifareClassic?) { - tagNfcA = null + init { tagMifare = mifare?.also { maxTransceiveLength = it.maxTransceiveLength / 4 + 1 } @@ -41,28 +32,27 @@ class Skylanders : TagTechnology { @Suppress("unused") var timeout: Int - get() = tagMifare?.timeout ?: tagNfcA?.timeout ?: 0 + get() = tagMifare?.timeout ?: 0 set(timeout) { tagMifare?.timeout = timeout - tagNfcA?.timeout = timeout } @Throws(IOException::class) override fun connect() { - tagMifare?.connect() ?: tagNfcA?.connect() + tagMifare?.connect() } override fun isConnected(): Boolean { - return tagMifare?.isConnected ?: tagNfcA?.isConnected ?: false + return tagMifare?.isConnected ?: false } @Throws(IOException::class) override fun close() { - tagMifare?.close() ?: tagNfcA?.close() + tagMifare?.close() } override fun getTag(): Tag? { - return tagMifare?.tag ?: tagNfcA?.tag + return tagMifare?.tag } private fun pseudoCrc48(crc: Long, data: List): Long { @@ -102,8 +92,11 @@ class Skylanders : TagTechnology { .joinToString("") { "%02x".format(it) }).toHexByteArray() } + @Throws(IOException::class) fun authenticate() { tagMifare?.let { + if (it.size != MifareClassic.SIZE_1K) + throw IOException(TagMo.appContext.getString(R.string.error_tag_format)) for (sector in 0 until 16) { val keyA = keySkylanders(it.tag.id.toHex(), sector) it.authenticateSectorWithKeyA(sector, keyA) @@ -114,7 +107,7 @@ class Skylanders : TagTechnology { fun transceive(data: ByteArray?): ByteArray? { return try { - tagMifare?.transceive(data) ?: tagNfcA?.transceive(data) + tagMifare?.transceive(data) } catch (e: IOException) { Debug.warn(e) null @@ -125,25 +118,13 @@ class Skylanders : TagTechnology { private infix fun Short.equals(i: Int): Boolean = this == i.toShort() - private fun getMifareClasssic(tag: Tag?): Skylanders? { - return MifareClassic.get(tag)?.let { Skylanders(it) } - } - - private fun getNfcA(tag: Tag?): Skylanders? { + operator fun get(tag: Tag?): Skylanders? { return NfcA.get(tag)?.let { - if (it.sak equals 0x09 && it.atqa.equals(byteArrayOf(0x00, 0x44))) - Skylanders(it) + if (it.sak equals 0x01 && it.atqa.equals(byteArrayOf(0x0F, 0x01))) + MifareClassic.get(tag)?.let { mifare -> Skylanders(mifare) } else null } } - - operator fun get(tag: Tag?): Skylanders? { - return try { - getMifareClasssic(tag)?.also { it.connect() } - } catch (e: IOException) { - getNfcA(tag)?.also { it.connect() } - } ?: getNfcA(tag)?.also { it.connect() } - } } } \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f706f6b78..7d94e27b1 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -378,6 +378,8 @@ Auth result was null Zip encoding not supported An unknown error has occurred. + Mifare Classic 1K required! + NXP chipset is required! Unable to contact update server! Update invalid! Please try again.