Skip to content

Capability container is not working as expected #4

@Shahvez1

Description

@Shahvez1

Hi, thanks for the amazing work, I am facing an issue while setting up capability container, I have followed your article on medium however when I try to set it then it becomes read only and I see No ndef data populated but I see url in ndef file contents and my url does not work while scanning here is the code. Please throw some light on this, thanks.

private fun runWorkerCC() {

    val worker = Thread(Runnable {
        var success = false
        try {
            dnaC = DnaCommunicator()
            try {
                dnaC!!.setTransceiver { bytesToSend -> isoDep!!.transceive(bytesToSend) }
            } catch (npe: java.lang.NullPointerException) {
                return@Runnable
            }
            dnaC!!.setLogger { info ->

            }
            dnaC!!.beginCommunication()


            // authentication
            var isLrpAuthenticationMode = false

            success = AESEncryptionMode.authenticateEV2(dnaC, ACCESS_KEY0, FACTORY_KEY)
            if (success) {
            } else {
                // if the returnCode is '919d' = permission denied the tag is in LRP mode authentication
                if (dnaC!!.lastCommandResult.status2 === PERMISSION_DENIED) {
                    // try to run the LRP authentication
                    success = LRPEncryptionMode.authenticateLRP(dnaC, ACCESS_KEY0, FACTORY_KEY)
                    if (success) {
                        isLrpAuthenticationMode = true
                    } else {

                        return@Runnable
                    }
                } else {

                    return@Runnable
                }
            }


            // write CC to file 01
            try {
                WriteData.run(dnaC, CC_FILE_NUMBER, NDEF_FILE_01_CAPABILITY_CONTAINER_R, 0)
            } catch (e: IOException) {
                
                return@Runnable
            }

// public static final byte[] NDEF_FILE_01_CAPABILITY_CONTAINER_R = Utils.hexStringToByteArray("000F55555A00340406E104010000FF"); // Free Read Access only, no Write Access

            // get the file settings
            var fileSettings01: FileSettings? = null
            try {
                fileSettings01 = GetFileSettings.run(dnaC, CC_FILE_NUMBER)
            } catch (e: java.lang.Exception) {
             
            }
            if (fileSettings01 == null) {
               
                return@Runnable
            }
            fileSettings01.readPerm = ACCESS_EVERYONE

            // write the file setings
            try {
                ChangeFileSettings.run(dnaC, CC_FILE_NUMBER, fileSettings01)
            } catch (e: IOException) {

                return@Runnable
            }

            // get File Settings for File 2 to get the key number necessary for writing (key 0 or key 2 ?)
            var fileSettings02: FileSettings? = null
            try {
                fileSettings02 = GetFileSettings.run(dnaC, NDEF_FILE_NUMBER)
            } catch (e: java.lang.Exception) {

            }
            if (fileSettings02 == null) {
                return@Runnable
            }
            
            val ACCESS_KEY_RW = fileSettings02.readWritePerm
            
            val ACCESS_KEY_CAR =
                fileSettings02.changePerm // we do need this information later when changing the file settings

            // in fabric settings or after unset the RW Access Key is 'Eh' = 14 meaning free read and write access
            // we have to skip an authentication with this key as it does not exist !
            if (ACCESS_KEY_RW == 14) {
                // do nothing, skip authentication
            } else {
                if (ACCESS_KEY_RW != ACCESS_KEY0) {
                    success = if (!isLrpAuthenticationMode) {
                        AESEncryptionMode.authenticateEV2(dnaC, ACCESS_KEY_RW, FACTORY_KEY)
                    } else {
                        LRPEncryptionMode.authenticateLRP(dnaC, ACCESS_KEY_RW, FACTORY_KEY)
                    }
                    if (!success) {

                        return@Runnable
                    }
                }
            }

            val sdmSettings = SDMSettings()
            sdmSettings.sdmEnabled =
                true // at this point we are just preparing the templated but do not enable the SUN/SDM feature
            sdmSettings.sdmMetaReadPerm = ACCESS_KEY3 // Set to a key to get encrypted PICC data
            sdmSettings.sdmFileReadPerm =
                ACCESS_KEY4 // Used to create the MAC and Encrypted File data
            sdmSettings.sdmReadCounterRetrievalPerm = ACCESS_NONE // Not sure what this is for
            sdmSettings.sdmOptionEncryptFileData = true
            var ndefRecord: ByteArray? = null
            val master = NdefTemplateMaster()
            master.usesLRP = isLrpAuthenticationMode
            master.fileDataLength =
                32 // encrypted file data available. The timestamp is 19 bytes long, but we need multiples of 16 for this feature
            sdmSettings.sdmOptionUid = true
            sdmSettings.sdmOptionReadCounter = true

            ndefRecord = master.generateNdefTemplateFromUrlString(
                "https://verify.abcd.com/tag?picc_data={PICC}&enc={FILE}&cmac={MAC}",
                sdmSettings
            )
            uid.value = byteArrayToHexString(GetCardUid.run(dnaC))

            try {
                WriteData.run(dnaC, NDEF_FILE_NUMBER, ndefRecord, 0)
            } catch (e: IOException) {


                return@Runnable
            }
            //System.out.println("*** NdefRecord: " + new String(ndefRecord, StandardCharsets.UTF_8));
            // write the timestamp data (19 characters long + 5 characters '#1234'
            val fileData: ByteArray =
                (getTimestampLog() + "#1234").toByteArray(
                    StandardCharsets.UTF_8
                )
            try {
                if (isLrpAuthenticationMode) {
                    WriteData.run(
                        dnaC,
                        NDEF_FILE_NUMBER,
                        fileData,
                        (87 + 16)
                    ) // LRP Encrypted PICC data is 16 bytes longer
                } else {
                    WriteData.run(dnaC, NDEF_FILE_NUMBER, fileData, 87)
                }
            } catch (e: IOException) {

                return@Runnable
            }


            // check if we authenticated with the right key - to change the key settings we need the CAR key
            if (ACCESS_KEY_CAR != ACCESS_KEY_RW) {
                success = if (!isLrpAuthenticationMode) {
                    AESEncryptionMode.authenticateEV2(dnaC, ACCESS_KEY_CAR, FACTORY_KEY)
                } else {
                    LRPEncryptionMode.authenticateLRP(dnaC, ACCESS_KEY_CAR, FACTORY_KEY)
                }
                if (!success) {

                    return@Runnable
                }
            }

            // change the auth key settings
            fileSettings02.sdmSettings = sdmSettings
            fileSettings02.readWritePerm = ACCESS_KEY2
            fileSettings02.changePerm = ACCESS_KEY0
            fileSettings02.readPerm = ACCESS_KEY2
            fileSettings02.writePerm = ACCESS_KEY2
            try {
                ChangeFileSettings.run(dnaC, NDEF_FILE_NUMBER, fileSettings02)
            } catch (e: IOException) {
                e.printStackTrace()
                return@Runnable
            }
        } catch (e: IOException) {

        }
        vibrateShort(context)

    })
    worker.start()
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions