25
HCE tutorial A simple wallet By Jensen

HCE tutorial

Embed Size (px)

Citation preview

Page 1: HCE tutorial

HCE tutorialA simple wallet

By Jensen

Page 2: HCE tutorial

Outline

• Running environment • APDU format• Registration HCE service • Registration AID• APDU command list• Applet AID define • APDU command define• processCommandApdu• Card Reader side, APDU define • Card Reader side, send APDU• Seek-for-android

Page 3: HCE tutorial

Running environment

• Card reader side • Java 8 (jre1.8.0.25)

• Android side• Android 4.4.2• Infocus M510

• IDE • Eclipse 4.4.1

• Code download• https://github.com/jensen0915/HCE_simple_wallet• https://github.com/jensen0915/HCE_simple_wallet_carder

Page 4: HCE tutorial

Application protocol data unit (APDU) format

Source: http://en.wikipedia.org/wiki/Smart_card_application_protocol_data_unit

Page 5: HCE tutorial

Registration HCE service

<service android:name="hce_demo.MyHostApduService" android:exported="true" android:permission="android.permission.BIND_NFC_SERVICE" > <intent-filter> <action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE" /> </intent-filter>

<meta-data android:name="android.nfc.cardemulation.host_apdu_service" android:resource="@xml/apduservice" /> </service>

Page 6: HCE tutorial

Registration AID

<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android" android:description="@string/servicedesc" android:requireDeviceUnlock="false" >

<aid-group android:category="other" android:description="@string/aiddescription" > <aid-filter android:name="F0394148148100" /> </aid-group>

</host-apdu-service>

Page 7: HCE tutorial

APDU command list

• Applet AID • Add money• Sub money• Check balance

Page 8: HCE tutorial

Applet AID define

private static final byte[] AID_SELECT_APDU = {(byte) 0x00, // CLA (class of command)(byte) 0xA4, // INS (instruction); A4 = select(byte) 0x04, // P1 (parameter 1) (0x04: select by name)(byte) 0x00, // P2 (parameter 2)(byte) 0x07, // LC (length of data) (byte) 0xF0, (byte) 0x39, (byte) 0x41, (byte) 0x48, (byte) 0x14, (byte) 0x81, (byte) 0x00,(byte) 0x00 // LE (max length of expected result, 0 implies 256)

};

Page 9: HCE tutorial

APDU command define

private boolean selectAddMoneyApdu(byte[] apdu) { //(byte) 0x80, // CLA//(byte) 0x01, // INS//(byte) 0x00, // P1//(byte) 0x00, // P2return apdu.length >= 2 && apdu[0] == (byte) 0x80 && apdu[1] == (byte) 0x01 && apdu[2] == (byte) 0x00 && apdu[3] == (byte) 0x00;

}

private boolean selectDebitApdu(byte[] apdu) { //(byte) 0x80, // CLA//(byte) 0x02, // INS//(byte) 0x00, // P1//(byte) 0x00, // P2return apdu.length >= 2 && apdu[0] == (byte) 0x80 && apdu[1] == (byte) 0x02 && apdu[2] == (byte) 0x00 && apdu[3] == (byte) 0x00;

}

Page 10: HCE tutorial

APDU command define (cont.)private boolean selectCheckBalanceApdu(byte[] apdu) {

//(byte) 0x80, // CLA//(byte) 0x03, // INS//(byte) 0x00, // P1//(byte) 0x00, // P2return apdu.length >= 2 && apdu[0] == (byte) 0x80 && apdu[1] == (byte) 0x03 && apdu[2] == (byte) 0x00 && apdu[3] == (byte) 0x00;

}

Page 11: HCE tutorial

processCommandApdu

@Overridepublic byte[] processCommandApdu(byte[] apdu, Bundle extras) {

String inboundApduDescription;byte[] responseApdu;

if (Arrays.equals(AID_SELECT_APDU, apdu)) {inboundApduDescription = "Application selected";Log.i("HCEDEMO", inboundApduDescription);byte[] answer = new byte[2];answer[0] = (byte) 0x90;answer[1] = (byte) 0x00;responseApdu = answer;return responseApdu;

}

Page 12: HCE tutorial

else if (selectAddMoneyApdu(apdu)) {Log.i("HCEDEMO", "ADD selected");int length = apdu[4];System.out.println("length = " + length);byte[] answer = new byte[3];

walletBalance = (byte)(walletBalance + apdu[5]);answer[0] = (byte) 0x90;answer[1] = (byte) 0x00;answer[2] = walletBalance;responseApdu = answer;return responseApdu;

}else if (selectDebitApdu(apdu)) {

Log.i("HCEDEMO", "Debit selected");int length = apdu[4];System.out.println("length = " + length);byte[] answer = new byte[3];

// balance can not be negativeif ( (byte)( (byte) walletBalance - apdu[5]) < (byte) 0 ) { answer[0] = (byte) 0x01;answer[1] = (byte) 0x02;responseApdu = answer;return responseApdu;

}

Page 13: HCE tutorial

else if (selectCheckBalanceApdu(apdu)) {

Log.i("HCEDEMO", "check balance selected");byte[] answer = new byte[3];answer[0] = (byte) 0x90;answer[1] = (byte) 0x00;answer[2] = walletBalance;responseApdu = answer;return responseApdu;

}

else {Log.i("HCEDEMO", "Unknown command");byte[] answer = new byte[2];answer[0] = (byte) 0x6F;answer[1] = (byte) 0x00;responseApdu = answer;return responseApdu;

}}

Page 14: HCE tutorial

Card Reader side, APDU define

//walletpublic static byte[] SelectAID = new byte[]{(byte) 0x00, (byte) 0xA4, (byte) 0x04, (byte) 0x00, (byte) 0x07,(byte) 0xF0, (byte) 0x39, (byte) 0x41, (byte) 0x48, (byte) 0x14, (byte) 0x81, (byte) 0x00, (byte) 0x00};

public static byte[] addMoney = new byte[]{(byte) 0x80, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x64};

public static byte[] subMoney = new byte[]{(byte) 0x80, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x34};

public static byte[] checkBalance = new byte[]{(byte) 0x80, (byte) 0x03, (byte) 0x00, (byte) 0x00};

Page 15: HCE tutorial

Card Reader side, send APDU

public static void main(String[] args) throws UnsupportedEncodingException {TerminalFactory terminalFactory = TerminalFactory.getDefault();try {

for (CardTerminal terminal : terminalFactory.terminals().list()) {System.out.println(terminal.getName());try {

Card card = terminal.connect("*");CardChannel channel = card.getBasicChannel();

System.out.println("SelectAID ");CommandAPDU command = new CommandAPDU(SelectAID);ResponseAPDU response = channel.transmit(command);byte recv[] = response.getBytes();for (int i = 0; i < recv.length; i++) {System.out.print(String.format("%02X", recv[i]));}System.out.println("");

}

Page 16: HCE tutorial

Demo

• Expectation output SelectAID 9000addMoney 900028subMoney 010200check balance 900028

Page 17: HCE tutorial

Seek-for-android

https://code.google.com/p/seek-for-android/

Page 18: HCE tutorial

Install Open Mobile API

• The Eclipse development environment needs to be configured in order to use the official SDK from Google as described in the Google documentation. In addition, the SDK needs to have access to the Open Mobile API addon package.

https://code.google.com/p/seek-for-android/wiki/UsingSmartCardAPI

Page 19: HCE tutorial
Page 20: HCE tutorial

AndroidManifest.xml

• <application• Add

<uses-library android:name="org.simalliance.openmobileapi" android:required="true" />

• <manifest• Add

<uses-permission android:name="org.simalliance.openmobileapi.SMARTCARD" />

Page 21: HCE tutorial

Register SEService

• Abstract function

Page 22: HCE tutorial

Binding SEService

• protected void onCreate(Bundle savedInstanceState) {

Page 23: HCE tutorial

Connection to SIM (secure element)

Page 24: HCE tutorial

Send APDU

Page 25: HCE tutorial

Face a problem

• Execution result • Reader openSession: service session is null.

• Unfortunately, we guess current open mobile API that doesn’t support HCE.