1

The AID of my app is F239856324897348 and I have constructed a SelectAID APDU for it. Now how do I actually send it to the receiving Android device which is using host card emulation.

I have a created my HCE service to respond with a response APDU as in this thread: How to define an APDU for STORE DATA for Host Card Emulation?

public static byte[] SelectAID = new byte[]{
        (byte) 0xF2, (byte) 0x39, (byte) 0x85, (byte) 0x63,
        (byte) 0x24, (byte) 0x89, (byte) 0x73, (byte) 0x48};

private void commandAPDU(byte[] apdu){
   //where do I go from here...
}

commandAPDU(SelectAID);
Michael Roland
  • 39,663
  • 10
  • 99
  • 206
Hazed 2.0
  • 133
  • 2
  • 14

1 Answers1

2

The format of APDUs is defined in ISO/IEC 7816-4. A typical SELECT (by AID) command looks like this:

+-----+-----+-----+-----+-----+-------------------------+-----+
| CLA | INS | P1  | P2  | Lc  | DATA                    | Le  |
+-----+-----+-----+-----+-----+-------------------------+-----+
| 00  | A4  | 04  | 00  | XX  | AID                     | 00  |
+-----+-----+-----+-----+-----+-------------------------+-----+

You could create it like this:

private byte[] selectApdu(byte[] aid) {
    byte[] commandApdu = new byte[6 + aid.length];
    commandApdu[0] = (byte)0x00;  // CLA
    commandApdu[1] = (byte)0xA4;  // INS
    commandApdu[2] = (byte)0x04;  // P1
    commandApdu[3] = (byte)0x00;  // P2
    commandApdu[4] = (byte)(aid.length & 0x0FF);       // Lc
    System.arraycopy(aid, 0, commandApdu, 5, aid.length);
    commandApdu[commandApdu.length - 1] = (byte)0x00;  // Le
    return commandApdu;
}

You could then send such APDU commands to a tag/HCE device discovered through the reader-mode API:

public abstract void onTagDiscovered(Tag tag) {
    IsoDep isoDep = IsoDep.get(tag);
    if (isoDep != null) {
        try {
            isoDep.connect();
            byte[] result = isoDep.transceive(selectApdu(SelectAID));
        } except (IOException ex) {
        } finally {
            try {
                isoDep.close();
            } except (Exception ignored) {}
        }
    }
}
Michael Roland
  • 39,663
  • 10
  • 99
  • 206
  • 1
    Ok so where are 00 A4 04 00 XX represented in the commandApdu array ? why is it not commandApdu[0] = (byte)0x00; commandApdu[1]=(byte)0xA4; commandApdu[2] = (byte)0x04 etc. ? Do i just write the AID string as Aid.toBytes() and pass it through selectApdu() ? How does it select the correct AID ? – Hazed 2.0 Jul 14 '18 at 13:05
  • @Hazed2.0 You got me again. Fixed. – Michael Roland Jul 14 '18 at 15:03
  • @Hazed2.0 The AID is passed as byte array (you already defined that as `SelectAID` in your code). You can't use `"F239856324897348".toBytes()` since that would give you UTF-8 coded bytes of the string and not the byte representation of the hexadecimal literal. – Michael Roland Jul 14 '18 at 15:07
  • Ok thanks makes more sense now. Also commandApdu[4] = (byte)(aid.length & 0x0FF); what is the significance of aid.length here ? Are we signifying the end of the byte array ? And is it 0xFF or 0x0FF ? – Hazed 2.0 Jul 14 '18 at 17:08
  • @Hazed2.0 commandApdu[4] contains the Lc field, i.e. the length of the command DATA field (which consists of the AID). There's no difference between 0xFF and 0x0FF since Java number literals are integers by default. I simply prefer the leading zero to make clear that it masks exactly one byte. – Michael Roland Jul 14 '18 at 19:08