Search code examples
androidxamarinnfcioexceptionmifare

Transceive fails on Android using Mifare Ultralight C card


I'm trying to send raw APDU commands to a Mifare Ultralight C card on Android (in Xamarin). Any command I send fails with an IOException ("Transceive failed").

Any toughts on this?

private static readonly string SELECT_CSN = "FFCA000000";

public void OnTagDiscovered(Android.Nfc.Tag tag)
{
    Log.Info(TAG, $"New tag discovered {ByteArrayToHexString(tag.GetId())}");

    var mifareTag = MifareUltralight.Get(tag);

    if(mifareTag != null)
    {
        mifareTag.Connect();

        byte[] cmd = HexStringToByteArray(SELECT_CSN);

        try
        {
            var response = mifareTag.Transceive(cmd);
        }
        catch (Java.IO.IOException ex)
        {
            Log.Error(TAG, $"Error with reading card {ex.Message}, {ex.StackTrace}");
        }
    }            
}

Solution

  • The reason you get an IOException is that the tag refuses the command (i.e. it responds with NAK) and resets itself. Note that on some Android devices you may receive the NAK answer instead of getting an IOException.

    The tag refuses the command because it is not a valid MIFARE Ultralight (C) command. MIFARE Ultralight (C) tags do not communicate using APDU commands, instead they use a proprieatry command set on top of ISO/IEC 14443-3. Valid commands for MIFARE Ultralight C are, for instance,

    • READ:
      +------+------+
      | 0x30 | ADDR |
      +------+------+
      
    • WRITE:
      +------+------+------+------+------+------+
      | 0x2A | ADDR | DATA                      |
      +------+------+------+------+------+------+
      
    • AUTHENTICATE (1):
      +------+------+
      | 0x1A | 0x00 |
      +------+------+
      

    The APDU command that you are trying to send (FFCA000000) seems to be a PC/SC reader command (clearly indicated by the otherwise invalid CLA byte 0xFF) for obtaining the UID of an enumerated tag. That is, this command requests information from the contactless smartcard reader and not from the tag itself. On Android, as you already found out, you would use tag.GetId() instead.