Android HCE(Host Card Emulation) JavaScript App alias Virtual JavaScript Smartcard

Die App zu diesem Artikel ist eigentlich aus drei Gründen entstanden:
* zur Evaluierung der Android HCE Funktionalität
* zur Evaluierung der Mozilla Rhino Bibliothek
* weil ich immer gern das passendes Tool parat habe

Was kann die App?

virtualjavascriptcard
Eigentlich nichts Grosses. Ein Byte-Array einem JavaScript (via Rhino-Bibliothek) übergeben und den Rückgabewert des JavaScripts wieder in ein Byte-Array konvertieren. Das einzig Spannende daran ist dass das HCE-Framework damit (via Aufruf der processApdu Funktion) befüllt wird. D.h. mit dem richtigen JavaScript-Code, den man selber editieren muss, kann man beliebige NFC Smartcards emulieren. Einziger Wermutstropfen: fehlende AIDs muessten bei Bedarf im Source-Code der App(!) ergänzt werden und die App müsste dann natürlich neu kompiliert und installiert werden. Aber diese Restriktion lässt sich bei einem gerooteten Gerät auch umgehen.

 

In der Praxis

Das einfachste JavaScript würde so aussehen:

function processApdu(apdu){
return new Array(0x90, 0x00);
}

Die virtuelle Karte würde jede Anfrage mit einem Statusword (SW) von 0x9000 (OK) quitieren.
Testen kann man das ganze wie folgt:
1. App installieren: APK-Datei direkt mit dem Smartphone runterladen und Installationsdialog bestätigen (Sicherheit | Geräteverwaltung | Installation aus andeten Quellen zulassen). Oder
1a. aus den Sourcen kompilieren, weil man evtl eine andere AID ergänzen möchte. Hierzu den Source herunterladen, AID mit folgender Zeile:

<aid-filter android:name="xxxxxxxxxxxx" />

in apduservice.xml ergänzen, mit dem SDK kompilieren und dann installieren. Optional könnte man
1b. Xposed-Framework nutzen: bei einem gerooteten Gerät kann man sich 1a auch sparen, wenn man das XposedModifyAidRouting-Modul nutzt. Hiermit können alle SELECT-Kommandos auf die App umgebogen werden und das Ergänzen von neuen/benötigten AIDs wird dynamisch erledigt.
2. JavaScript evtl verändern: nach dem ersten Start der App kann die HCE.js Datei auf den per USB-Kabel angeschlossenen PC editiert werden. Hierzu die Datei erst vom Android Gerät per adb (befindet sich im Android SDK) kopieren, zB:

~/adt-bundle-linux-x86_64-20130219/sdk/platform-tools/adb pull /sdcard/VirtualJavaScriptCard/HCE.js ~/HCE.js

Nun das Skript je nach Wunsch anpassen, zB alle Kommandos mit der Ausgabe eines File Control Information (FCI) Templates für Mastercard beantworten (macht zwar kein Sinn soll nur ein Beispiel sein)

function processApdu(apdu) {
return new Array(0x6F, 0x23, 0x84, 0x0E, 0x32, 0x50, 0x41, 0x59, 0x2E, 0x53, 0x59, 0x53, 0x2E, 0x44, 0x44, 0x46, 0x30, 0x31, 0xA5, 0x11, 0xBF, 0x0C, 0x0E, 0x61, 0x0C, 0x4F, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x04, 0x30, 0x60, 0x87, 0x01, 0x01, 0x90, 0x00);
}

Danach die editierte Datei einfach wieder auf das Gerät zurück kopieren:

~/adt-bundle-linux-x86_64-20130219/sdk/platform-tools/adb push ~/HCE.js /sdcard/VirtualJavaScriptCard/HCE.js

3. Interaktion mit Smartcard Reader testen, zB mit MySmartcardIOShell (interaktive Shell zum Senden von APDUs):

$ java -cp ./MySmartCardIOShell.jar -Dsun.security.smartcardio.library=/lib/x86_64-linux-gnu/libpcsclite.so.1 MySmartCardIOShell

Android Gerät auf den Kontaktlos-Reader des PCs legen, verbinden und APDU senden. Mit dem Nexus10 würde das ganze ungefähr so aussehen:

-/term
0: REINER SCT cyberJack RFID basis 0, sun.security.smartcardio.TerminalImpl, card present: true
protocol: T=1, ATR: 3b 80 80 01 01
>/sel 325041592E5359532E4444463031
=> 00 a4 04 00 0e 32 50 41 59 2e 53 59 53 2e 44 44
46 30 31
<= 6F 23 84 0E 32 50 41 59 2E 53 59 53 2E 44 44 46
30 31 A5 11 BF 0C 0E 61 0C 4F 07 A0 00 00 00 04
30 60 87 01 01 90 00
Status: OK
>

Das gewünschte JavaScript wird durch Auswahl in der Checkbox-Liste der App aktiviert, die App muss aber nicht aktiv sein um Anfragen zu beantworten, da hierfür eine Implementierung des HostApduService im Hintergrund läuft.

Probleme

Wenn mehr als 1 App zum Bezahlen installiert ist kann man unter Einstellungen | Mobil bezahlen die gewünschte App auswählen. Aus Evaluierungszwecke war auf meinem Tablet die Tapp App installiert (und mit keinem Account verknüpft). Diese Konstellation führte dazu dass entsprechende SELECT Kommandos nicht beantwortet werden konnten und die aufrufende Reader Anwendung hing. Nach Auswahl der VirtualJavaScriptCard App als Bezahl-App war das Problem behoben.

payment_select

Ausserdem kann man emulierte Karte nur mit Android Devices ab 4.4 auslesen, da hierfür der NFC-Controller in einen speziellen Modus mit enableReaderMode gesetzt werden und Android Beam ausgeschaltet sein muss.

Auf meinem Nexus 10 scheint sich der Broadcomm NFC-Controller ab und zu mal zu verabschieden. Dann hilft nur ein deaktivieren der NFC-Funktionalität mit anschliessender Re-Aktivierung.

Beispiel: Kreditkarte / PPSE

Mit dem beigefügten HCE_PPSE.js Skript kann man bereits Teile einer Kreditkarte emulieren. Cardpeek zeigt zB folgende Daten an:screenshot-cardpeek-emv

Oder man schaut sich mit dem MasterCard Terminal Simulator an welche Kommandos an die Karte gesendet werden:

screenshot_mastercard_terminal_simulator

Links

Virtual JavaScriptCard App – Source Code https://github.com/rena2019/VirtualJavaScriptCard
XposedModifyAidRouting https://github.com/johnzweng/XposedModifyAidRouting
Blogartikel: List of HCE (Host Card Emulation) Apps

10 thoughts on “Android HCE(Host Card Emulation) JavaScript App alias Virtual JavaScript Smartcard”

  1. Klasse Projekt, hat mir bei meiner Implemetierung von HCE sehr geholfen! Noch eine Frage: Wo kann die apk-Datei runtergeladen werden? Bislang sind nur die sourcen verlinkt.

      1. Ich hatte vor aehnlich wie du eine Karte per Konfigfile zu simulieren um in unserem Netzbetrieb schnell mal was zu testen. Leider gibt es im LG G2 wohl ein Fehler in der KitKat-Implementierung. Aus diesem Grund kam das Projekt gerade zum stehen. Ich ueberlege nun entweder ein Mod zu flashen oder aufs naechste Stockupdate zu warten. Ueber die apk wuerde ich mich sehr freuen.

      2. Hi dzierzwa, „Mifare Classic 1k card Emulation“ wird von Android nicht unterstützt und wird es höchstens mit einem NXP controller bzw einem controller, der Mifare4Mobile unterstützt geben. Die UID ist bei Android 4.4 vom controller abhängig, bisher habe ich nur eine Random UID (wechselt bei jedem Reset) gesehen. Mit welchem Gerät hast Du denn eine feste UID bekommen?

  2. Lässt sich damit auch eine Mifare Classic 1k Karte emulieren ? (wegen “ beliebige NFC Smartcards emulieren“) Wäre top🙂

  3. Danke für die Antwort. Ich habe unter anderem auch eine ISO14443-4 Karte hier liegen. Hier haben wir ja mehr Infos gespeichert (Serial,Batchnr,Productiondate,vendor,…) Wie lassen sich formal diese Parameter in der js definieren ? Damit der leser hier auch die Karte formal wieder erkennt ? Hast du damit schon Erfahrung?

    1. Hi Marcel,
      Du kannst mit der aktuellen Android HCE API und damit mit meiner JavaScript HCE App nur APDUs austauschen. Das ist alles. Du kannst weder UID, ATRs, etc beinflussen, denn die werden vom Android System bzw NFC Controller bereitsgestellt. Vielleicht sollte ich mal meinen halb fertigen Blogartikel „Was ist alles mit HCE möglich?“ veröffentlichen…

Schreibe einen Kommentar

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s