David Reinberger
David Reinberger

Reputation: 540

IsoDep APDU SELECT returns 6FXX

I am trying to implement IsoDep reading capabilities to chariotsolutions phongap-nfc plugin, so far (even though i am a complete newbie to Java/android and cordova/phonegap) I have managed to make it work with cordova, connect to the card, issue an APDU command and return it back to the web view. (hooray for me right?)

Well the simple problem is that I did not manage to get a 9000 response so far by selecting the application.

I am using LG L [email protected].

Additions to NFCplugin.java + import nfc.tech.IsoDep, NFCa, NFCb

.... else if (action.equalsIgnoreCase(ISODEP)) {
        registerIsoDep(callbackContext);    

    } else if (action.equalsIgnoreCase(READISODEP)){
        readIsoDep(callbackContext);

    } else .....

This should be the tag listener - i think so :-)

private void registerIsoDep(CallbackContext callbackContext) throws JSONException {

    addTechList(new String[]{IsoDep.class.getName()});
    callbackContext.success();

}

This reads the IsoDep tag, found out that it has to be called within the callback of the previous function (will get back in to that in the Js part)

private void readIsoDep(final CallbackContext callbackContext) throws JSONException {

    final Tag tag = savedIntent.getParcelableExtra(NfcAdapter.EXTRA_TAG);

    cordova.getThreadPool().execute(new Runnable() {
        @Override
        public void run() {
            IsoDep isoDep = IsoDep.get(tag);

            try {

                isoDep.connect();

                isoDep.setTimeout(5000);

                byte[] SELECT = { 
                    (byte) 0x00, // CLA Class           
                    (byte) 0xA4, // INS Instruction     
                    (byte) 0x04, // P1  Parameter 1
                    (byte) 0x00, // P2  Parameter 2
                    (byte) 0x07, // Length
                    (byte) 0xA0, (byte) 0x00, 
                    (byte) 0x00, (byte) 0x00, 
                    (byte) 0x04, (byte) 0x10, 
                    (byte) 0x10, // AID
                    (byte) 0x00 // Lenght
                };

                try {
                    byte[] result = isoDep.transceive(SELECT);

                    isoDep.close();

                    callbackContext.success(result[0] + "|" + result[1]);

                }catch (IOException e) {
                    callbackContext.error("error" + e);
                }

            } catch (IOException e) {
                callbackContext.error("error" + e);
            }
        }
    });

}

Cordova implementation

,addIDDiscoverListener: function(callback, win, fail) {
        document.addEventListener("tag", callback, false);
        cordova.exec(win, fail, "NfcPlugin", "registerIsoDep", []);
    }

};

var isoDep = {
     readIsoDep: function(win, fail) {
         cordova.exec(win, fail, "NfcPlugin", "readIsoDep", []);
    }

}

And lastly "app.js"

 nfc.addIDDiscoverListener(function(nfcEvent) {

        //listenes for the isodep tag

        isoDep.readIsoDep(function(tag) {

            console.log(tag); //returns ADPU response codes

        }, function(reason) {
            console.log('error!   ' + reason);
        });

    },
    function() {
        console.log('registered reader');
    },
    function(reason) {
        console.log('error!   ' + reason);
    });

My problem is that no matter what app id I select whether it is MasterCard (A0000000041010) with the above one or PPES (proximity payment system environment), I get this error. Since this is my first attempt to do Java I do not know if it is an implementation issue or command issue (which should be fine) most of this code was written by looking at the chariot solutions code and literally thinking yea this should work, this is here so it should be probably be also here ("cordova execute runnable" - i know sh*t what it does, just assumed it should probably be in my code also).

Also there is probably another small bug - it reads the card only ONCE until I quit the app and start it again.

PS.: I have read a ton of SO post, googled like hell for couple of days and tried a lot of things (learned a couple also) but none of them were able to help me.

PSS.: And yes when it is done I want to merge it the the original project.

Thank for any help and sorry for the long post.

Upvotes: 1

Views: 1802

Answers (1)

Michael Roland
Michael Roland

Reputation: 40851

The 6F XX that you are seeing is not the status word. In fact 6F ... is exactly what you should receive when your SELECT (by DF name) command succeeds. 6F is the tag of an FCI template.

When you try to retrieve the status word, you are actually reading the first two bytes of the array that you get from the transceive() method. However, a response APDU looks like

+---------+--------+--------+
|  DATA   |  SW1   |  SW2   |
| n bytes | 1 byte | 1 byte |
+---------+--------+--------+

So you would need to check the last two bytes of result for the status word:

result[result.length - 2] + "|" + result[result.length - 1]

Upvotes: 2

Related Questions