SlideShare a Scribd company logo
HCE tutorial
A simple wallet
By Jensen
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
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
Application protocol data unit (APDU) format
Source: http://en.wikipedia.org/wiki/Smart_card_application_protocol_data_unit
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>
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>
APDU command list
• Applet AID
• Add money
• Sub money
• Check balance
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)
};
APDU command define
private boolean selectAddMoneyApdu(byte[] apdu) {
//(byte) 0x80, // CLA
//(byte) 0x01, // INS
//(byte) 0x00, // P1
//(byte) 0x00, // P2
return 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, // P2
return apdu.length >= 2 && apdu[0] == (byte) 0x80 && apdu[1] == (byte) 0x02
&& apdu[2] == (byte) 0x00 && apdu[3] == (byte) 0x00;
}
APDU command define (cont.)
private boolean selectCheckBalanceApdu(byte[] apdu) {
//(byte) 0x80, // CLA
//(byte) 0x03, // INS
//(byte) 0x00, // P1
//(byte) 0x00, // P2
return apdu.length >= 2 && apdu[0] == (byte) 0x80 && apdu[1] == (byte) 0x03
&& apdu[2] == (byte) 0x00 && apdu[3] == (byte) 0x00;
}
processCommandApdu
@Override
public 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;
}
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 negative
if ( (byte)( (byte) walletBalance - apdu[5]) < (byte) 0 ) {
answer[0] = (byte) 0x01;
answer[1] = (byte) 0x02;
responseApdu = answer;
return responseApdu;
}
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;
}
}
Card Reader side, APDU define
//wallet
public 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};
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("");
}
Demo
• Expectation output
SelectAID
9000
addMoney
900028
subMoney
010200
check balance
900028
Seek-for-android
https://code.google.com/p/seek-for-android/
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
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" />
Register SEService
• Abstract function
Binding SEService
• protected void onCreate(Bundle savedInstanceState) {
Connection to SIM (secure element)
Send APDU
Face a problem
• Execution result
• Reader openSession: service session is null.
• Unfortunately, we guess current open mobile API that doesn’t
support HCE.

More Related Content

PDF
Camera2 API, SHIM, and HAL 3.2 in Android 5.1
PPTX
PDF
React and redux
PPTX
NodeJS guide for beginners
PDF
Design and Concepts of Android Graphics
PDF
게임서버프로그래밍 #1 - IOCP
PPTX
Flutter talkshow
PDF
Hybrid Apps with Angular & Ionic Framework
Camera2 API, SHIM, and HAL 3.2 in Android 5.1
React and redux
NodeJS guide for beginners
Design and Concepts of Android Graphics
게임서버프로그래밍 #1 - IOCP
Flutter talkshow
Hybrid Apps with Angular & Ionic Framework

What's hot (20)

PDF
openFrameworks – パーティクルを動かす、静的配列と動的配列 - 多摩美メディアアートII
PDF
Celery: The Distributed Task Queue
PPTX
Intro to Node.js (v1)
PPTX
Android graphic system (SurfaceFlinger) : Design Pattern's perspective
PPTX
Binder: Android IPC
PDF
Cours 3 les directives
PPTX
Android audio system(audiopolicy_manager)
PDF
Project meeting: Android Graphics Architecture Overview
PDF
Servlet vs Reactive Stacks in 5 Use Cases
PDF
React-cours.pdf
PDF
Control Your Network ASICs, What Benefits switchdev Can Bring Us
PDF
[143] Modern C++ 무조건 써야 해?
PDF
Android IPC Mechanism
PDF
Support NodeJS avec TypeScript Express MongoDB
PPTX
Concurrency Patterns with MongoDB
PDF
Multiplatform Apps with Spring, Kotlin, and RSocket
PPTX
AngularJS - Présentation (french)
PPT
PDF
02 correction-td smi-s3-algo2
PDF
WebXR: Introducing Mixed Reality and the Immersive Web - Peter O'Shaughnessy ...
openFrameworks – パーティクルを動かす、静的配列と動的配列 - 多摩美メディアアートII
Celery: The Distributed Task Queue
Intro to Node.js (v1)
Android graphic system (SurfaceFlinger) : Design Pattern's perspective
Binder: Android IPC
Cours 3 les directives
Android audio system(audiopolicy_manager)
Project meeting: Android Graphics Architecture Overview
Servlet vs Reactive Stacks in 5 Use Cases
React-cours.pdf
Control Your Network ASICs, What Benefits switchdev Can Bring Us
[143] Modern C++ 무조건 써야 해?
Android IPC Mechanism
Support NodeJS avec TypeScript Express MongoDB
Concurrency Patterns with MongoDB
Multiplatform Apps with Spring, Kotlin, and RSocket
AngularJS - Présentation (french)
02 correction-td smi-s3-algo2
WebXR: Introducing Mixed Reality and the Immersive Web - Peter O'Shaughnessy ...
Ad

Viewers also liked (14)

PDF
Android HCE: An intro into the world of NFC
PPTX
Host Card Emulation
PDF
What is Host Card Emulation (HCE)?
PDF
Host Card Emulation in Android: What Does it Mean?
PDF
What is Payment Tokenization?
PPTX
HCE and Beyond: How Early Opportunities Can Accelerate NFC Growth
PDF
The Impact of HCE on NFC Adoption
PPTX
HCE cloud payments internet services August 2015
PPTX
Cloud payments (HCE): a simpler step with Thales HSMs
PDF
What is a Token Service Provider?
PPTX
NFC And HCE 2016 - What’s Next?
PPT
Nfc ppt
PPTX
NEAR FIELD COMMUNICATION
PPTX
NFC technical presentation
Android HCE: An intro into the world of NFC
Host Card Emulation
What is Host Card Emulation (HCE)?
Host Card Emulation in Android: What Does it Mean?
What is Payment Tokenization?
HCE and Beyond: How Early Opportunities Can Accelerate NFC Growth
The Impact of HCE on NFC Adoption
HCE cloud payments internet services August 2015
Cloud payments (HCE): a simpler step with Thales HSMs
What is a Token Service Provider?
NFC And HCE 2016 - What’s Next?
Nfc ppt
NEAR FIELD COMMUNICATION
NFC technical presentation
Ad

Recently uploaded (20)

PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PDF
gpt5_lecture_notes_comprehensive_20250812015547.pdf
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PDF
Spectral efficient network and resource selection model in 5G networks
PDF
Electronic commerce courselecture one. Pdf
PPTX
A Presentation on Artificial Intelligence
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PDF
Empathic Computing: Creating Shared Understanding
PDF
Video forgery: An extensive analysis of inter-and intra-frame manipulation al...
PDF
cuic standard and advanced reporting.pdf
PDF
Encapsulation theory and applications.pdf
PPTX
Tartificialntelligence_presentation.pptx
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PPTX
1. Introduction to Computer Programming.pptx
PDF
Accuracy of neural networks in brain wave diagnosis of schizophrenia
PDF
Getting Started with Data Integration: FME Form 101
PPTX
Machine Learning_overview_presentation.pptx
PPTX
MYSQL Presentation for SQL database connectivity
PDF
Approach and Philosophy of On baking technology
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
Digital-Transformation-Roadmap-for-Companies.pptx
gpt5_lecture_notes_comprehensive_20250812015547.pdf
Advanced methodologies resolving dimensionality complications for autism neur...
Spectral efficient network and resource selection model in 5G networks
Electronic commerce courselecture one. Pdf
A Presentation on Artificial Intelligence
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
Empathic Computing: Creating Shared Understanding
Video forgery: An extensive analysis of inter-and intra-frame manipulation al...
cuic standard and advanced reporting.pdf
Encapsulation theory and applications.pdf
Tartificialntelligence_presentation.pptx
Mobile App Security Testing_ A Comprehensive Guide.pdf
1. Introduction to Computer Programming.pptx
Accuracy of neural networks in brain wave diagnosis of schizophrenia
Getting Started with Data Integration: FME Form 101
Machine Learning_overview_presentation.pptx
MYSQL Presentation for SQL database connectivity
Approach and Philosophy of On baking technology
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx

HCE tutorial

  • 1. HCE tutorial A simple wallet By Jensen
  • 2. 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
  • 3. 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
  • 4. Application protocol data unit (APDU) format Source: http://en.wikipedia.org/wiki/Smart_card_application_protocol_data_unit
  • 5. 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>
  • 6. 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>
  • 7. APDU command list • Applet AID • Add money • Sub money • Check balance
  • 8. 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) };
  • 9. APDU command define private boolean selectAddMoneyApdu(byte[] apdu) { //(byte) 0x80, // CLA //(byte) 0x01, // INS //(byte) 0x00, // P1 //(byte) 0x00, // P2 return 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, // P2 return apdu.length >= 2 && apdu[0] == (byte) 0x80 && apdu[1] == (byte) 0x02 && apdu[2] == (byte) 0x00 && apdu[3] == (byte) 0x00; }
  • 10. APDU command define (cont.) private boolean selectCheckBalanceApdu(byte[] apdu) { //(byte) 0x80, // CLA //(byte) 0x03, // INS //(byte) 0x00, // P1 //(byte) 0x00, // P2 return apdu.length >= 2 && apdu[0] == (byte) 0x80 && apdu[1] == (byte) 0x03 && apdu[2] == (byte) 0x00 && apdu[3] == (byte) 0x00; }
  • 11. processCommandApdu @Override public 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; }
  • 12. 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 negative if ( (byte)( (byte) walletBalance - apdu[5]) < (byte) 0 ) { answer[0] = (byte) 0x01; answer[1] = (byte) 0x02; responseApdu = answer; return responseApdu; }
  • 13. 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; } }
  • 14. Card Reader side, APDU define //wallet public 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};
  • 15. 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(""); }
  • 18. 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
  • 20. AndroidManifest.xml • <application • Add <uses-library android:name="org.simalliance.openmobileapi" android:required="true" /> • <manifest • Add <uses-permission android:name="org.simalliance.openmobileapi.SMARTCARD" />
  • 22. Binding SEService • protected void onCreate(Bundle savedInstanceState) {
  • 23. Connection to SIM (secure element)
  • 25. Face a problem • Execution result • Reader openSession: service session is null. • Unfortunately, we guess current open mobile API that doesn’t support HCE.