3
votes

I want to send an APDU with a length of 1699 bytes via NFC (class IsoDep) to a Java Card smartcard. I get the error

java.io.IOException: Transceive length exceeds supported maximum

My phone is a Samsung Galaxy S7.

I use extended-length in my applet on the card. I have verified that the card supports extended length. I tested this via pyapdutool by sending an APDU with 4000 bytes to the card.

I found that when I write this code, the result is false:

final Tag t = (Tag) tag;
myTag = IsoDep.get(t);
boolean result = myTag.isExtendedLengthApduSupported();

I have this in my manifest:

<activity
        android:name=".test"
        android:label="@string/title_test"
        android:launchMode="singleTop"
        android:theme="@style/AppTheme.NoActionBar" >
    <action android:name="android.nfc.action.TAG_DISCOVERED" />
    <category android:name="android.intent.category.DEFAULT" />
    <intent-filter>
        <action android:name="android.nfc.action.NDEF_DISCOVERED" />
    </intent-filter>
</activity>

How can I send an APDU with 1699 bytes (or any length greater than 261 bytes) through Android NFC?

1
the topic is unsolved to my knowledgePaul Bastian
It is not clear, whether the card supports such a length. Did you try it from a desktop PC and worked it there?guidot
Even my laptop which sports an NFC chip doesn't support extended length. Unfortunately it's the same story all over again. First "normal" smart card readers didn't support Extended Length, then they did in an extremely buggy way, and nowadays there seem only minor issues left. I presume it will go the same way for NFC chips (although these are even cheaper, so it may take even more time).Maarten Bodewes

1 Answers

3
votes

Short answer: You can't easily do that.

You already found out that IsoDep does not "support" extended-length APDUs on your device (i.e. isoDep.isExtendedLengthApduSupported() returns false). In fact this does not mean that you can't send extended-length APDUs through the IsoDep object. It actually only means that the IsoDep object won't properly split extended-length APDUs across more than two ISO-DEP blocks and consequently an APDU that is longer than 261 bytes will be assumed to exceed the transmit buffer size. You should still be able to send extended-length APDUs with sizes <= 261 bytes.

So isoDep.isExtendedLengthApduSupported() actually indicates if you can send more than 261 bytes in one ISO-DEP transceive.

What you could do to overcome this problem is to not use the IsoDep object at all and, instead, manually implement ISO-DEP (the ISO/IEC 14443-4 transmission protocol) on top of the NfcA object (if your card is based on NFC-A / ISO/IEC 14443 Type A) or the NfcB object (if your card is based on NFC-B / ISO/IEC 14443 Type B and if your device supports exchanging data over the NfcB object). You could then split your extended-length APDUs into ISO-DEP blocks that are small enough for the transceive buffer of the NFC controller (typically 253 bytes including the header bytes, excluding the CRC bytes). However, handling the ISO-DEP protocol yourself also means that you have to take care of proper ISO-DEP activation, of handling block numbering, block acknowledgements, timeouts, waiting-time extension, etc. Which is rather complicated, and particularly timeouts are not easy to observe due to the delays through the Android NFC stack.