diff --git a/tangem-card-new/src/main/java/com/tangem/common/apdu/CommandApdu.kt b/tangem-card-new/src/main/java/com/tangem/common/apdu/CommandApdu.kt new file mode 100644 index 0000000000..103d88649e --- /dev/null +++ b/tangem-card-new/src/main/java/com/tangem/common/apdu/CommandApdu.kt @@ -0,0 +1,102 @@ +package com.tangem.common.apdu + +import com.tangem.EncryptionMode +import com.tangem.common.tlv.Tlv +import com.tangem.common.tlv.toBytes +import java.io.ByteArrayOutputStream + +class CommandApdu( + + private val instruction: Int, + private val tlvList: List, + + private val cla: Byte = ISO_CLA, + private val p1: Byte = 0x00, + private val p2: Byte = 0x00, + + private val le: Int = 0x00, + + private val encryptionMode: EncryptionMode = EncryptionMode.NONE, + private val encryptionKey: ByteArray? = null) { + + + fun toBytes(): ByteArray { + +// var length = 4 // CLA, INS, P1, P2 + + val data = if (tlvList.isNotEmpty()) { + tlvList.toBytes() + } else { + byteArrayOf() + } + + val lc = data.size +// +// if (data.isNotEmpty()) { +// length += 1 // LC +// if (lc >= 256) +// length += 2 +// length += data.size // DATA +// } + + + val byteStream = ByteArrayOutputStream() + byteStream.write(cla.toInt()) + byteStream.write(instruction) + byteStream.write(p1.toInt()) + byteStream.write(p2.toInt()) + if (lc != 0) { + writeLength(byteStream, lc) + byteStream.write(data) + } + return byteStream.toByteArray() + +// val apdu = ByteArray(length) +// +// var index = 0 +// apdu[index] = cla +// index++ +// apdu[index] = instruction +// index++ +// apdu[index] = p1 +// index++ +// apdu[index] = p2 +// index++ +// if (lc != 0) { +// if (lc < 256) { +// apdu[index] = lc.toByte() +// index++ +// } else { +// apdu[index] = 0 +// index++ +// apdu[index] = (lc shr 8).toByte() +// index++ +// apdu[index] = (lc and 0xFF).toByte() +// index++ +// } +// +// System.arraycopy(data, 0, apdu, index, data.size) +// index += data.size +// } +// return apdu + } + + private fun writeLength(stream: ByteArrayOutputStream, lc: Int) { +// if (lc < 256) { +// stream.write(lc) +// } else { + stream.write(0) + stream.write(lc shr 8) + stream.write(lc and 0xFF) +// } + } + + + private fun encrypt() { + + } + + companion object { + const val ISO_CLA = 0x00.toByte() + } +} \ No newline at end of file diff --git a/tangem-card-new/src/main/java/com/tangem/common/apdu/ResponseApdu.kt b/tangem-card-new/src/main/java/com/tangem/common/apdu/ResponseApdu.kt new file mode 100644 index 0000000000..c35b699505 --- /dev/null +++ b/tangem-card-new/src/main/java/com/tangem/common/apdu/ResponseApdu.kt @@ -0,0 +1,37 @@ +package com.tangem.common.apdu + +import com.tangem.common.tlv.Tlv +import com.tangem.enums.Status + +class ResponseApdu(val data: ByteArray) { + + val sw1: Int = 0x00FF and data[data.size - 2].toInt() + val sw2: Int = 0x00FF and data[data.size - 1].toInt() + + val sw: Int = sw1 shl 8 or sw2 + + val status: Status = Status.byCode(sw) + + fun getTlvData(encryptionKey: ByteArray? = null): List? { + val tlvs = when { + data.size < 2 -> null + data.size == 2 -> emptyList() + else -> Tlv.fromBytes(data.copyOf(data.size - 2)) + } + return flattenNestedTlvs(tlvs) + } + + private fun flattenNestedTlvs(tlvs: List?): List? = + tlvs?.flatMap { + if (it.tag.hasNestedTlv()) { + Tlv.fromBytes(it.value) + } else { + listOf(it) + } + } + + private fun decrypt(encryptionKey: ByteArray) { + + } + +} \ No newline at end of file diff --git a/tangem-card-new/src/main/java/com/tangem/common/extentions/ByteArray.kt b/tangem-card-new/src/main/java/com/tangem/common/extentions/ByteArray.kt new file mode 100644 index 0000000000..dfb049f3cb --- /dev/null +++ b/tangem-card-new/src/main/java/com/tangem/common/extentions/ByteArray.kt @@ -0,0 +1,31 @@ +package com.tangem.common.extentions + +import java.nio.ByteBuffer +import java.security.MessageDigest +import java.util.* +import kotlin.experimental.and + + +fun ByteArray.toHexString() = joinToString("") { "%02x".format(it) } + + +fun ByteArray.toInt(): Int { + return when (this.size) { + 1 -> (this[0] and 0xFF.toByte()).toInt() + 2 -> ByteBuffer.wrap(this).short.toInt() + 4 -> ByteBuffer.wrap(this).int + else -> throw IllegalArgumentException("Length must be 1,2 or 4. Length = " + this.size) + } +} + +fun ByteArray.toDate(): Date { + val year = ((this[0] and 0xFF.toByte()).toInt() shl 8) or (this[1] and 0xFF.toByte()).toInt() + val month = this[2] - 1 + val day = this[3].toInt() + val cd = Calendar.getInstance() + cd.set(year, month, day, 0, 0, 0) + return cd.time +} + +fun ByteArray.calculateSha512(): ByteArray = MessageDigest.getInstance("SHA-512").digest(this) + diff --git a/tangem-card-new/src/main/java/com/tangem/common/extentions/String.kt b/tangem-card-new/src/main/java/com/tangem/common/extentions/String.kt new file mode 100644 index 0000000000..656d46bd9e --- /dev/null +++ b/tangem-card-new/src/main/java/com/tangem/common/extentions/String.kt @@ -0,0 +1,20 @@ +package com.tangem.common.extentions + +import java.nio.charset.Charset +import java.security.MessageDigest + + +fun String.calculateSha256(): ByteArray { + val sha256 = MessageDigest.getInstance("SHA-256") + val data = this.toByteArray(Charset.forName("UTF-8")) + return sha256.digest(data) +} + +fun String.hexToBytes(): ByteArray { + val bytes = ByteArray(this.length / 2) + for (i in bytes.indices) { + bytes[i] = Integer.parseInt(this.substring(2 * i, 2 * i + 2), + 16).toByte() + } + return bytes +} \ No newline at end of file diff --git a/tangem-card-new/src/main/java/com/tangem/common/tlv/Tlv.kt b/tangem-card-new/src/main/java/com/tangem/common/tlv/Tlv.kt new file mode 100644 index 0000000000..7ccd7d11b2 --- /dev/null +++ b/tangem-card-new/src/main/java/com/tangem/common/tlv/Tlv.kt @@ -0,0 +1,80 @@ +package com.tangem.common.tlv + +import java.io.ByteArrayInputStream +import java.io.IOException + +class Tlv(val tag: TlvTag, val tagCode: Int, val value: ByteArray = byteArrayOf()) { + + +companion object { + fun tlvFromBytes(stream: ByteArrayInputStream): Tlv? { + val code = stream.read() + if (code == -1) return null + var len = stream.read() + if (len == -1) + throw IOException("Can't read TLV") + if (len == 0xFF) { + val lenH = stream.read() + if (lenH == -1) + throw IOException("Can't read TLV") + len = stream.read() + if (len == -1) + throw IOException("Can't read TLV") + len = len or (lenH shl 8) + } + val value = ByteArray(len) + if (len > 0) { + if (len != stream.read(value)) { + throw IOException("Can't read TLV") + } + } + val tag = TlvTag.byCode(code) + return Tlv(tag, code, value) + } + + + + fun fromBytes(mData: ByteArray): List { + val tlvList = mutableListOf() + val stream = ByteArrayInputStream(mData) + var tlv: Tlv? = null + do { + try { + tlv = Tlv.tlvFromBytes(stream) + if (tlv != null) tlvList.add(tlv) + } catch (e: IOException) { + throw TlvMapperException("TLVError: " + e.message) + } + + } while (tlv != null) + return tlvList + } +} + +} + +fun List.toBytes(): ByteArray = + this.map { it.toBytes() }.reduce { arr1, arr2 -> arr1 + arr2 } + +fun Tlv.toBytes(): ByteArray { + val tag = byteArrayOf(this.tag.code.toByte()) + val length = getLengthInBytes(this.value.size) + val value = if (this.value.isNotEmpty()) this.value else byteArrayOf(0x00) + return tag + length + value +} + +private fun getLengthInBytes(tlvLength: Int): ByteArray { + return if (tlvLength > 0) { + if (tlvLength > 0xFE) { + byteArrayOf( + 0xFF.toByte(), + (tlvLength shr 8 and 0xFF).toByte(), + (tlvLength and 0xFF).toByte() + ) + } else { + byteArrayOf((tlvLength and 0xFF).toByte()) + } + } else { + byteArrayOf() + } +} \ No newline at end of file diff --git a/tangem-card-new/src/main/java/com/tangem/common/tlv/TlvMapper.kt b/tangem-card-new/src/main/java/com/tangem/common/tlv/TlvMapper.kt new file mode 100644 index 0000000000..9e707415c5 --- /dev/null +++ b/tangem-card-new/src/main/java/com/tangem/common/tlv/TlvMapper.kt @@ -0,0 +1,96 @@ +package com.tangem.common.tlv + +import com.tangem.commands.CardStatus +import com.tangem.commands.EllipticCurve +import com.tangem.commands.ProductMask +import com.tangem.commands.SigningMethod +import com.tangem.common.extentions.toDate +import com.tangem.common.extentions.toHexString +import com.tangem.common.extentions.toInt +import com.tangem.data.SettingsMask +import java.util.* + + +open class TlvMapperException(message: String?) : Exception(message) + +class MissingTagException(message: String? = null) : TlvMapperException(message) +class WrongTypeException(message: String? = null) : TlvMapperException(message) +class ConvertionException(message: String? = null) : TlvMapperException(message) + +class TlvMapper(val tlvList: List) { + + inline fun mapOptional(tag: TlvTag): T? = + try { + map(tag) + } catch (exception: MissingTagException) { + null + } + + inline fun map(tag: TlvTag): T { + val tlvValue: ByteArray = tlvList.find { it.tag == tag }?.value + ?: throw MissingTagException() + + return when (tag.valueType()) { + TlvValueType.HexString -> { + if (T::class != String::class) + throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}") + tlvValue.toHexString() as T + } + TlvValueType.Utf8String -> { + if (T::class != String::class) + throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}") + String(tlvValue) as T + } + TlvValueType.IntValue -> { + if (T::class != Integer::class) + throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}") + tlvValue.toInt() as T + } + TlvValueType.BoolValue -> { + if (T::class != Boolean::class) + throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}") + true as T + } + TlvValueType.ByteArray -> { + if (T::class != ByteArray::class) + throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}") + tlvValue as T + } + TlvValueType.EllipticCurve -> { + if (T::class != EllipticCurve::class) + throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}") + EllipticCurve.byName(String(tlvValue)) as T + } + TlvValueType.DateTime -> { + if (T::class != Date::class) + throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}") + tlvValue.toDate() as T + } + TlvValueType.ProductMask -> { + if (T::class != ProductMask::class) + throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}") + ProductMask.byCode(tlvValue.first()) as T + + } + TlvValueType.SettingsMask -> { + if (T::class != SettingsMask::class) + throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}") + SettingsMask(tlvValue.toInt()) as T + + } + TlvValueType.CardStatus -> { + if (T::class != CardStatus::class) + throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}") + CardStatus.byCode(tlvValue.toInt()) as T + } + TlvValueType.SigningMethod -> { + if (T::class != SigningMethod::class) + throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}") + SigningMethod.byCode(tlvValue.toInt()) as T + } + } + + + } + +} \ No newline at end of file diff --git a/tangem-card-new/src/main/java/com/tangem/enums/TlvTag.kt b/tangem-card-new/src/main/java/com/tangem/common/tlv/TlvTag.kt similarity index 57% rename from tangem-card-new/src/main/java/com/tangem/enums/TlvTag.kt rename to tangem-card-new/src/main/java/com/tangem/common/tlv/TlvTag.kt index 62625b6fd0..33ecc7a0a2 100644 --- a/tangem-card-new/src/main/java/com/tangem/enums/TlvTag.kt +++ b/tangem-card-new/src/main/java/com/tangem/common/tlv/TlvTag.kt @@ -1,12 +1,12 @@ -package com.tangem.enums +package com.tangem.common.tlv enum class TlvTag(val code: Int) { Unknown(0x00), - CardID(0x01), + CardId(0x01), Status(0x02), CardPublicKey(0x03), CardSignature(0x04), - CurveID(0x05), + CurveId(0x05), HashAlgID(0x06), SigningMethod(0x07), MaxSignatures(0x08), @@ -49,9 +49,9 @@ enum class TlvTag(val code: Int) { CodePageCount(0x41), CodeHash(0x42), - TrOutHash(0x50), - TrOutHashSize(0x51), - TrOutRaw(0x52), + TransactionOutHash(0x50), + TransactionOutHashSize(0x51), + TransactionOutRaw(0x52), WalletPublicKey(0x60), Signature(0x61), @@ -66,6 +66,11 @@ enum class TlvTag(val code: Int) { ManufacturerPublicKey(0x85), CardIdManufacturerSignature(0x86), + ProductMask(0x8A), + PaymentFlowVersion(0x54), + UserCounter(0x2C), + + TokenSymbol(0xA0), TokenContractAddress(0xA1), TokenDecimal(0xA2), @@ -78,7 +83,34 @@ enum class TlvTag(val code: Int) { TerminalPublicKey(0x5C), TerminalTransactionSignature(0x57); + fun hasNestedTlv(): Boolean { + return when (this) { + TlvTag.CardData -> true + else -> false + } + } + + fun valueType(): TlvValueType { + return when (this) { + CardId, Pin, Batch -> TlvValueType.HexString + ManufactureId, Firmware, IssuerId, BlockchainId, TokenSymbol, TokenContractAddress -> + TlvValueType.Utf8String + CurveId -> TlvValueType.EllipticCurve + MaxSignatures, PauseBeforePin2, RemainingSignatures, + SignedHashes, Health, TokenDecimal, UserCounter -> TlvValueType.IntValue + IsActivated, TerminalIsLinked -> TlvValueType.BoolValue + ManufactureDateTime -> TlvValueType.DateTime + ProductMask -> TlvValueType.ProductMask + SettingsMask -> TlvValueType.SettingsMask + Status -> TlvValueType.CardStatus + SigningMethod -> TlvValueType.SigningMethod + else -> TlvValueType.ByteArray + } + } + + companion object { fun byCode(code: Int): TlvTag = values().find { it.code == code } ?: Unknown } -} \ No newline at end of file +} + diff --git a/tangem-card-new/src/main/java/com/tangem/common/tlv/TlvValueType.kt b/tangem-card-new/src/main/java/com/tangem/common/tlv/TlvValueType.kt new file mode 100644 index 0000000000..c71a19fa4a --- /dev/null +++ b/tangem-card-new/src/main/java/com/tangem/common/tlv/TlvValueType.kt @@ -0,0 +1,15 @@ +package com.tangem.common.tlv + +enum class TlvValueType { + HexString, + Utf8String, + IntValue, + BoolValue, + ByteArray, + EllipticCurve, + DateTime, + ProductMask, + SettingsMask, + CardStatus, + SigningMethod +} \ No newline at end of file diff --git a/tangem-card-new/src/main/java/com/tangem/crypto/CryptoUtils.kt b/tangem-card-new/src/main/java/com/tangem/crypto/CryptoUtils.kt new file mode 100644 index 0000000000..c71858135f --- /dev/null +++ b/tangem-card-new/src/main/java/com/tangem/crypto/CryptoUtils.kt @@ -0,0 +1,20 @@ +package com.tangem.crypto + +import com.tangem.commands.EllipticCurve +import java.security.SecureRandom + +fun generateRandomBytes(length: Int): ByteArray { + val bytes = ByteArray(length) + SecureRandom().nextBytes(bytes) + return bytes +} + +fun verify(publicKey: ByteArray, message: ByteArray, signature: ByteArray, + curve: EllipticCurve = EllipticCurve.Secp256k1): Boolean { + return when (curve) { + EllipticCurve.Secp256k1 -> verifySecp256k1(publicKey, message, signature) + EllipticCurve.Ed25519 -> verifyEd25519(publicKey, message, signature) + } +} + + diff --git a/tangem-card-new/src/main/java/com/tangem/crypto/Ed25519.kt b/tangem-card-new/src/main/java/com/tangem/crypto/Ed25519.kt new file mode 100644 index 0000000000..a825889aec --- /dev/null +++ b/tangem-card-new/src/main/java/com/tangem/crypto/Ed25519.kt @@ -0,0 +1,27 @@ +package com.tangem.crypto + +import com.tangem.common.extentions.calculateSha512 +import net.i2p.crypto.eddsa.EdDSAEngine +import net.i2p.crypto.eddsa.EdDSAPublicKey +import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable +import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec +import java.security.MessageDigest +import java.security.PublicKey + +internal fun verifyEd25519(publicKey: ByteArray, message: ByteArray, signature: ByteArray): Boolean { + val messageSha512 = message.calculateSha512() + val loadedPublicKey = loadPublicKey(publicKey) + val spec = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.ED_25519) + val signatureInstance = EdDSAEngine(MessageDigest.getInstance(spec.hashAlgorithm)) + signatureInstance.initVerify(loadedPublicKey) + + signatureInstance.update(messageSha512) + + return signatureInstance.verify(signature) +} + +private fun loadPublicKey(publicKeyArray: ByteArray): PublicKey { + val spec = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.ED_25519) + val pubKey = EdDSAPublicKeySpec(publicKeyArray, spec) + return EdDSAPublicKey(pubKey) +} \ No newline at end of file diff --git a/tangem-card-new/src/main/java/com/tangem/crypto/Sepc256k1.kt b/tangem-card-new/src/main/java/com/tangem/crypto/Sepc256k1.kt new file mode 100644 index 0000000000..a85e7cf8be --- /dev/null +++ b/tangem-card-new/src/main/java/com/tangem/crypto/Sepc256k1.kt @@ -0,0 +1,43 @@ +package com.tangem.crypto + +import org.spongycastle.asn1.ASN1EncodableVector +import org.spongycastle.asn1.ASN1Integer +import org.spongycastle.asn1.DERSequence +import org.spongycastle.jce.ECNamedCurveTable +import org.spongycastle.jce.spec.ECPublicKeySpec +import java.math.BigInteger +import java.security.KeyFactory +import java.security.PublicKey +import java.security.Signature + +internal fun verifySecp256k1(publicKey: ByteArray, message: ByteArray, signature: ByteArray): Boolean { + val signatureInstance = Signature.getInstance("SHA256withECDSA") + val loadedPublicKey = loadPublicKey(publicKey) + signatureInstance.initVerify(loadedPublicKey) + signatureInstance.update(message) + + val v = ASN1EncodableVector() + val size = signature.size / 2 + v.add(calculateR(signature, size)) + v.add(calculateS(signature, size)) + val sigDer = DERSequence(v).encoded + + return signatureInstance.verify(sigDer) +} + +private fun loadPublicKey(publicKeyArray: ByteArray): PublicKey { + + val spec = ECNamedCurveTable.getParameterSpec("secp256k1") + val factory = KeyFactory.getInstance("EC", "SC") + + val p1 = spec.curve.decodePoint(publicKeyArray) + val keySpec = ECPublicKeySpec(p1, spec) + + return factory.generatePublic(keySpec) +} + +private fun calculateR(signature: ByteArray, size: Int): ASN1Integer = + ASN1Integer(BigInteger(1, signature.copyOfRange(0, size))) + +private fun calculateS(signature: ByteArray, size: Int): ASN1Integer = + ASN1Integer(BigInteger(1, signature.copyOfRange(size, size * 2))) \ No newline at end of file diff --git a/tangem-card-new/src/main/java/com/tangem/data/CommandApdu.kt b/tangem-card-new/src/main/java/com/tangem/data/CommandApdu.kt deleted file mode 100644 index 0ec5f29219..0000000000 --- a/tangem-card-new/src/main/java/com/tangem/data/CommandApdu.kt +++ /dev/null @@ -1,75 +0,0 @@ -package com.tangem.data - -import com.tangem.enums.Instruction - -class CommandApdu( - val tlvList: List, - val instruction: Instruction, - val p1: Int = 0x00, - val p2: Int = 0x00, - val encryptionKey: ByteArray? = null, - val rawInstruction: ByteArray = byteArrayOf()) { - - val cla = ISO_CLA - - - fun serialize(): ByteArray { - - var length = 4 // CLA, INS, P1, P2 - - val data = if (tlvList.isNotEmpty()) { - tlvList.toBytes() - } else { - byteArrayOf() - } - - val lc = data.size - - if (data.isNotEmpty()) { - length += 1 // LC - if (lc >= 256) - length += 2 - length += data.size // DATA - } - - val apdu = ByteArray(length) - - var index = 0 - apdu[index] = cla - index++ - apdu[index] = instruction.code.toByte() - index++ - apdu[index] = p1.toByte() - index++ - apdu[index] = p2.toByte() - index++ - if (lc != 0) { - if (lc < 256) { - apdu[index] = lc.toByte() - index++ - } else { - apdu[index] = 0 - index++ - apdu[index] = (lc shr 8).toByte() - index++ - apdu[index] = (lc and 0xFF).toByte() - index++ - } - - System.arraycopy(data, 0, apdu, index, data.size) - index += data.size - } - return apdu - - - } - - - private fun encrypt() { - - } - - companion object { - const val ISO_CLA = 0x00.toByte() - } -} \ No newline at end of file diff --git a/tangem-card-new/src/main/java/com/tangem/data/ResponseApdu.kt b/tangem-card-new/src/main/java/com/tangem/data/ResponseApdu.kt deleted file mode 100644 index 1d859869e1..0000000000 --- a/tangem-card-new/src/main/java/com/tangem/data/ResponseApdu.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.tangem.data - -import com.tangem.enums.Status - -class ResponseApdu(val data: ByteArray) { - - private val tlvParser = TlvParser() - - fun deserialize(encryptionKey: ByteArray? = null): ResponseApduParsed? { - - if (data.size < 2) return null - - if (data.size == 2) return ResponseApduParsed(parseStatus(data[0], data[1]), emptyList()) - - val tlvList = tlvParser.fromBytes(data.copyOf(data.size - 2)) - val sw1 = data[data.size - 2] - val sw2 = data[data.size -1] - return ResponseApduParsed(parseStatus(sw1, sw2), tlvList) - } - - private fun parseStatus(sw1: Byte, sw2: Byte): Status { - val code = (0x00FF and sw1.toInt()) shl 8 or (0x00FF and sw2.toInt()) - return Status.byCode(code) - } - - private fun decrypt(encryptionKey: ByteArray) { - - } - -} - -data class ResponseApduParsed(val status: Status, val tlvList: List? = null, val parsingError: String? = null) { - fun statusCompleted(): Boolean = status == Status.ProcessCompleted -} \ No newline at end of file diff --git a/tangem-card-new/src/main/java/com/tangem/data/SettingsMask.kt b/tangem-card-new/src/main/java/com/tangem/data/SettingsMask.kt new file mode 100644 index 0000000000..696b947202 --- /dev/null +++ b/tangem-card-new/src/main/java/com/tangem/data/SettingsMask.kt @@ -0,0 +1,32 @@ +package com.tangem.data + +data class SettingsMask(val rawValue: Int) { + + companion object{ + const val IsReusable = 0x0001 + const val UseActivation = 0x0002 + const val ForbidPurgeWallet = 0x0004 + const val UseBlock = 0x0008 + + const val AllowSwapPIN = 0x0010 + const val AllowSwapPIN2 = 0x0020 + const val UseCVC = 0x0040 + const val ForbidDefaultPIN = 0x0080 + + const val UseOneCommandAtTime = 0x0100 + const val UseNDEF = 0x0200 + const val UseDynamicNDEF = 0x0400 + const val SmartSecurityDelay = 0x0800 + + const val Protocol_AllowUnencrypted = 0x1000 + const val Protocol_AllowStaticEncryption = 0x2000 + + const val ProtectIssuerDataAgainstReplay = 0x4000 + + const val AllowSelectBlockchain = 0x8000 + + const val DisablePrecomputedNDEF = 0x00010000 + + const val SkipSecurityDelayIfValidatedByLinkedTerminal = 0x00080000 + } +} \ No newline at end of file diff --git a/tangem-card-new/src/main/java/com/tangem/data/Tlv.kt b/tangem-card-new/src/main/java/com/tangem/data/Tlv.kt deleted file mode 100644 index 450801ccdf..0000000000 --- a/tangem-card-new/src/main/java/com/tangem/data/Tlv.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.tangem.data - -import com.tangem.enums.TlvTag - -class Tlv(val tag: TlvTag, val tagCode: Int, val value: ByteArray = byteArrayOf()) - -fun List.toBytes(): ByteArray = - this.map { it.toBytes() }.reduce { arr1, arr2 -> arr1 + arr2 } - -fun Tlv.toBytes(): ByteArray { - val tag = byteArrayOf(this.tag.code.toByte()) - val length = getLengthInBytes(this.value.size) - val value = if (this.value.isNotEmpty()) this.value else byteArrayOf(0x00) - return tag + length + value -} - -private fun getLengthInBytes(tlvLength: Int): ByteArray { - return if (tlvLength < 0) { - if (tlvLength > 0xFE) { - byteArrayOf( - 0xFF.toByte(), - (tlvLength shr 8 and 0xFF).toByte(), - (tlvLength and 0xFF).toByte() - ) - } else { - byteArrayOf((tlvLength and 0xFF).toByte()) - } - } else { - byteArrayOf() - } -} diff --git a/tangem-card-new/src/main/java/com/tangem/data/TlvParser.kt b/tangem-card-new/src/main/java/com/tangem/data/TlvParser.kt deleted file mode 100644 index 06e0839e5c..0000000000 --- a/tangem-card-new/src/main/java/com/tangem/data/TlvParser.kt +++ /dev/null @@ -1,55 +0,0 @@ -package com.tangem.data - -import com.tangem.enums.TlvTag -import java.io.ByteArrayInputStream -import java.io.IOException - -class TlvParser { - - fun readFromStream(stream: ByteArrayInputStream): Tlv? { - val code = stream.read() - if (code == -1) return null - var len = stream.read() - if (len == -1) - throw IOException("Can't read TLV") - if (len == 0xFF) { - val lenH = stream.read() - if (lenH == -1) - throw IOException("Can't read TLV") - len = stream.read() - if (len == -1) - throw IOException("Can't read TLV") - len = len or (lenH shl 8) - } - val value = ByteArray(len) - if (len > 0) { - if (len != stream.read(value)) { - throw IOException("Can't read TLV") - } - } - val tag = TlvTag.byCode(code) - return Tlv(tag, code, value) - } - - fun fromBytes(data: ByteArray): List { - val tlvList = mutableListOf() - val stream = ByteArrayInputStream(data) - var tlv: Tlv? = null - do { - try { - tlv = readFromStream(stream) - if (tlv != null) tlvList.add(tlv) - } catch (e: IOException) { - throw IOException("TLVError: " + e.message) - } - - } while (tlv != null) - return tlvList - } - - - fun parseTlv(data: ByteArray) { - - - } -} \ No newline at end of file diff --git a/tangem-card-new/src/main/java/com/tangem/enums/Status.kt b/tangem-card-new/src/main/java/com/tangem/enums/Status.kt index 4a6b8922f2..16658a60db 100644 --- a/tangem-card-new/src/main/java/com/tangem/enums/Status.kt +++ b/tangem-card-new/src/main/java/com/tangem/enums/Status.kt @@ -6,7 +6,7 @@ enum class Status (val code: Int, val description: String){ InvalidParams(0x6A86, "SW_INVALID_PARAMS"), ErrorProcessingCommand(0x6286, "SW_ERROR_PROCESSING_COMMAND"), InvalidState(0x6985, "SW_INVALID_STATE"), -// PinsNotChanged(ProcessCompleted.code, ProcessCompleted.description), + // PinsNotChanged(ProcessCompleted.code, ProcessCompleted.description), Pin1Changed(ProcessCompleted.code + 0x0001, "SW_PIN1_CHANGED"), Pin2Changed(ProcessCompleted.code + 0x0002, "SW_PIN2_CHANGED"), PinsChanged(ProcessCompleted.code + 0x0003, "SW_PINS_CHANGED"),