Matthias Wuttke
Matthias Wuttke

Reputation: 2032

Mifare DESFIRE EV1 GetCardUid

The following code works and allows me to get the UID of a Mifare 1k card. Unfortunately, it does not work with Desfire cards.

    public byte[] GetUid()
    {
        byte[] uid = new byte[6];
        int rc = Communicate(new byte[]{0xff, 0xca, 0x00, 0x00, 0x04}, ref uid);
        if (rc != 0)
            throw new Exception("failure: " + rc);

        int rc1, rc2;
        if (uid.Length == 2)
        {
            rc1 = uid[0];
            rc2 = uid[1];
        }
        else
        {
            rc1 = uid[4];
            rc2 = uid[5];
        }

        if (rc1 != 0x90 || rc2 != 0x00)
            throw new Exception("failure: " + rc1 + "/" + rc2);

        byte[] result = new byte[4];
        Array.Copy(uid, result, 4);
        return result;
    }

I had a look at following resources

... and tried to do it like this:

        byte[] outb = new byte[15];
        int rc9 = Communicate(new byte[] { 0x60 }, ref outb);

outb always contains { 0x67, 0x00 } and not, as expected, { af 04 01 01 00 02 18 05 }.

Connect is sucessful, and SCardGetAttrib allows me to fetch the ATR. The Communicate method works with SCardTransmit. I can post the code if it helps.

Thanks for any pointer!

EDIT:

Thanks for the first answer! I changed the program as suggested:

        byte[] outb = new byte[9];
        int rc5 = Communicate(new byte[]{0x90, 0x60, 0x00, 0x00, 0x00, 0x00}, ref outb);

Now outb is { 0x91, 0x7E }. This seems to be better, 0x91 looking like an ISO 7816 response code, but unfortunately not 0x90, as expected. (I also had a look at the DESFIRE_TRANSCEIVE macro in the second link that continues reading if it receives 0xf2.) I tried a Google search for ISO 7816 APDU response codes, but had no success in decoding the error code.

EDIT 2:

I also found the following comment:

with an omnikey 5321 I get DESFire ATR 3B8180018080 UID 04 52 2E AA 47 23 80 90 00 [from apdu FFCA000000] All other apdu give 917E unknown error

This explains my error code and gives me another hint, FFCA000000 looking quite similar to my other Mifare 1k string. So with FFCA000000 I get a 9 byte response that seem to contain the UID. Interestingly, the FFCA000000 code also works with the 1k cards, so maybe my solution is just to change the last 04 to 00 and deal with responses of different length. Right?

EDIT 3:

It seems the penny has dropped... 0x04 = 4 bytes response = too small for a 7 byte UID = response 917E = buffer too small :-)

Upvotes: 0

Views: 8628

Answers (3)

Marc
Marc

Reputation: 21

Cla=ff commands are pcsc part 3 commands. Ins=ca should work with any cl reader that is pcsc 2.0x compliant

Upvotes: 2

Matthias Wuttke
Matthias Wuttke

Reputation: 2032

This code seems to work:

        int rc = Communicate(new byte[] { 0xff, 0xca, 0x00, 0x00, 0x00 }, ref uid);
        if (rc != 0)
            throw new Exception("failure: " + rc);

        int rc1 = uid[uid.Length-2], rc2 = uid[uid.Length-1];

        if (rc1 != 0x90 || rc2 != 0x00)
            throw new Exception("failure: " + rc1 + "/" + rc2);

        byte[] result = new byte[uid.Length - 2];
        Array.Copy(uid, result, uid.Length - 2);
        return result;

Any comments?

Upvotes: 3

Maarten Bodewes
Maarten Bodewes

Reputation: 93968

Try the "Native wrapped" version of the first link you supplied instead. Your interface expects ISO 7816-4 style APDU's (as it returns an ISO 7816-4 status word meaning wrong length).

Upvotes: 1

Related Questions