Android HCE response 6A82

miron123 picture miron123 · Jul 7, 2014 · Viewed 7k times · Source

Im currently working on a HCE implementation for my Galaxy s4. I have a Omnikey 5321-cl reader which supportes 7816-4. My android class looks like this:

public class NfcHceService extends HostApduService{
private int counter         = 0;

@Override
public void onStart(android.content.Intent intent, int startId)
{
    new Thread(new Runnable() {

        @Override
        public void run()
        {
            while (true)
            {
                Log.d("HCE", String.valueOf(counter));
                counter++;
                try
                {
                    Thread.sleep(1000);
                } catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
            }
        }
    }).run();
}

@Override
public byte[] processCommandApdu(byte[] apdu, Bundle extras)
{
    byte[] response = null;
    if (apdu[2] == 0xA4)
    {
        // return selecting applet
        response = new byte[] { (byte) 0x90, 0x00 };

    }
    return response;
}

@Override
public void onDeactivated(int reason)
{
    android.os.Debug.waitForDebugger();
    Log.d("HCE", "onDeactivated");

}

}

And my reader class looks like this:

private static final byte[] CLA_INS_P1_P2   = { 0x00, (byte) 0xA4, 0x04, 0x00 };
private static final byte[] AID_ANDROID     = { (byte) 0xF0, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };

private static byte[] createSelectAidApdu(byte[] aid)
{
    byte[] result = new byte[6 + aid.length];
    System.arraycopy(CLA_INS_P1_P2, 0, result, 0, CLA_INS_P1_P2.length);
    result[4] = (byte) (aid.length);
    System.arraycopy(aid, 0, result, 5, aid.length);
    result[result.length - 1] = 10;
    return result;
}

public static void Create_MF() throws CardException
{

    // --Variable declaration
    Card card = null;
    ResponseAPDU answer = null;
    // ---------------------------------------------

    // --1--Establish connection with the smart card
    TerminalFactory factory = TerminalFactory.getDefault();
    List<CardTerminal> terminals = factory.terminals().list();
    // Use the first terminal
    CardTerminal terminal = terminals.get(1);
    // Connect with the card
    card = terminal.connect("*");
    CardChannel channel = card.getBasicChannel();
    // ---------------------------------------------

    byte[] selectAidApdu = createSelectAidApdu(AID_ANDROID);

    answer = channel.transmit(new CommandAPDU(selectAidApdu));

My AID for the hce service is F0010203040506.

My Problem now is that I get a correct Select APDU on my android device which looks like this:

> RX: Type 4 Tag Command (13 bytes)
  CLA:0x00
  INS:0xA4(Select)
  P1:0x04(Name)
  P2:0x00(First or Only)
  LC:0x07(7)
  Data(7 bytes)
   00: f0 01 02 03 04 05 06
  Le:0x0A(10)

But I get a response code 6A82. As I understand it, this means that the device doesn t find the service. But I dont understand why. Can anybody help?

Manifest:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.hce"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
    android:minSdkVersion="19"
    android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.nfc.hce" />
<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <service
        android:name=".NfcHceService"
        android:exported="false"
        android:permission="android.permission.BIND_NFC_SERVICE" >
        <intent-filter>
            <action android:name="android.nfc.cardemulation.HOST_APDU_SERVICE" />
        </intent-filter>
        <meta-data
            android:name="android.nfc.cardemulation.host_apdu_service"
            android:resource="@xml/hce_service" />
    </service>
</application>

And the xml file:

<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/my_app_hce_service" >
<aid-group
    android:category="other"
    android:description="@string/my_app_aid_group" >
    <aid-filter android:name="F0010203040506" />
</aid-group></host-apdu-service>

Update

public static void Create_MF() throws CardException
{

    // --Variable declaration
    Card card = null;
    ResponseAPDU answer = null;
    // ---------------------------------------------

    // --1--Establish connection with the smart card
    TerminalFactory factory = TerminalFactory.getDefault();
    List<CardTerminal> terminals = factory.terminals().list();
    // Use the first terminal
    CardTerminal terminal = terminals.get(1);
    // Connect with the card
    card = terminal.connect("*");
    CardChannel channel = card.getBasicChannel();
    // ---------------------------------------------

    byte[] selectAidApdu = { 0x00, (byte) 0xA4, 0x04, 0x00, 0x07, (byte) 0xF0, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 }; // createSelectAidApdu(AID_ANDROID);

    answer = channel.transmit(new CommandAPDU(selectAidApdu));}

UPDATE 2

I tried to implement the isDefaultServiceForAid(). But Im not sure if Im using it correctly and if it does what I want.

    CardEmulation card = CardEmulation.getInstance(NfcAdapter.getDefaultAdapter(this));
    ComponentName comp = new ComponentName(getApplicationContext(), NfcHceService.class);
    boolean tmp = card.isDefaultServiceForAid(comp, "F0010203040506");

Does it really test the AID of my service or does it something else? I want to test if my service is accessable with the AID I specified in my hce_service.xml which is declared in my Manifest.

Answer

jim picture jim · Jul 7, 2014

The error 6A82 means file not found.

In this case it means that the AID you are selecting does not exist.

This is probably due to a mismatch between the AID you are selecting e.g. f0 01 02 03 04 05 06 and the AID specified in your AndroidManifest.xml

ISO 7816 Reference here

Update:

From inspecting your updated code it looks like you are adding another byte to the end of the APDU i.e. 0x10. Try removing the following line from the function createSelectAidApdu()

result[result.length - 1] = 10;

Also, i'm not sure why you set the last byte to be 10, which is equals 16 in decimal. Note that the last byte is often used to specify the amount of data expected/requested from the target device. It is not always required, which is the case for the select application command.