Schlagwort-Archive: JavaCard

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

Advertisements

Log0x9000 – Poor Mans NFC Smartcard Logger

Vor längerer Zeit habe ich ein bisschen mit JavaCards rumgespielt: Applets kodiert, auf kontaktlose Smartcard geladen und an mein NFC Smartphone gehalten. Eine wirklich sinnvolle Idee für ein Applet kam mir irgendwie nicht bis zu dem Zeitpunkt als ich wissen wollte welche Daten (APDUs) eine bestimmte Android NFC App eigentlich so an (m)eine kontaktlose Smartcard sendet und welche Daten (Response-APDUs) auslesen werden. Da kam mir die Idee zu einer Dummy Smartcard, die jede Anfrage (Command-APDU) mitloggt, mit einer OK-Quitierung (Response-APDU: 0x9000) versieht und somit relativ preiswert das Erforschen der Kommunikation zwischen NFC App und Smartcard zulässt. Ausserdem kann man damit nebenbei schlecht kodierte NFC Apps zum Absturz bringen 🙂  Wird nämlich eine Response-APDU 0x9000 mit zusätzlichen Daten erwartet und bleibt das Datenfeld leer so kann es zB zu einer ArrayIndexOutOfBoundsException kommen.

Erforderlich dafür ist allerdings eine JavaCard, die das Setzen des Default Selected Privilege zulässt, da dann alle APDUs (auch das Selektieren eines nichtvorhandenen Applets) direkt an das Logging-Applet geleitet werden. Die Blank 64k Programmable JAVA SIM Card zB kann man dafür leider nicht verwenden, da die Karte das Laden/Installieren mit Privilegien per Global Platform nicht unterstützt.

Folgende Kommandos sind in der ersten lauffähigen Version implementiert:

00100000 get version (zeigt die Applet Version an)
00400200076C6F6739303030 logging = off (t0/t1/tcl off) (schaltet das Logging aus, Karte kann nun konfiguriert werden)
004002xx logging = on (bitwise) e.g:
00400201 logging = on @ t0 contact interface
00400202 logging = on @ t1 contact interface
00400204 logging = on @ tcl contactless interface
00400207 logging = on @ all contact and contactless interfaces
00400210 get logging setting (liest Logging Bits aus)
00400300 clear log (clear all log entries)
00400400 clear cr_apdus (
0041p1p2 set defaultSW p1p2=9000, 6D00, 6a80 (Default SW setzen)
00420000 get defaultSW (Default SW auslesen)
00500100 activate C/R-APDU: lc {data set}  {data-set}={len-apdu apdu-byte1...apdu-byteN len-response-apdu rapdu0... rapduN}  
00510000 get cr_index (number of C/R-APDUs) (Anzahl der konfigurierten C/R-APDUs ausgeben)
006000nn readLog n (Logeintrag n auslesen)
00610000 get log index (Anzahl der Logeinträge auslesen)

Somit kann das Logging an- und ausgeschaltet werden, Logeinträge gelöscht / konfiguriert werden und vorhandene Logeinträge aufgelistet werden.

Testkandiat

Als Proband musste die Electronic Pickpocket RFID von Identity Stronghold herhalten. Im Screenshot sieht man das angeblich eine Karte erkannt wurde.

identify_stronghold

Die geloggte APDU zeigen die Anfrage der App:

#selektieren des American Express AIDs
00 a4 04 00 05 a0 00 00 00 25

Scheinbar fragt die App nur nach einer American Express Karte.

Hall of Shame

Schlecht kodierte (ohne Überprüfung der Response APDU und ohne try-catch-Block) NFC Apps scheinen dann so auszusehen:
ec_kreditkarten_infos  speek  s-kontaktlos

Interessant ist auch der Unterschied zwischen einem Android-Gerät mit NXP NFC Controller und einem Android-Gerät mit STMicroelectronics-Oberthur-Broadcom-Gespann. Mein Nexus S (mit NXP-NFC-Controller) sendet keine weiteren APDUs wenn das Phone auf die Karte gelegt wird, während das Nexus 10 (Broadcom-NFC-Controller) scheinbar alle 0.5 Sekunden versucht eine Leseanfrage an die Karte zu senden – denn nach 10 Sekunden wurden folgende APDUs geloggt:

> l9ls
0: 00B000009000
1: 00B000009000
2: 00B000009000
3: 00B000009000
4: 00B000009000
5: 00B000009000
6: 00B000009000
7: 00B000009000
8: 00B000009000
9: 00B000009000
10: 00B000009000
11: 00B000009000
12: 00B000009000
13: 00B000009000
14: 00B000009000
15: 00B000009000
16: 00B000009000
17: 00B000009000
18: 00B000009000
19: 00B000009000

Das 00B00000 entspricht einem READ-BINARY-Kommando, das wahrscheinlich genutzt wird um zu überprüfen, ob sich die Karte noch im Feld befindet.

Antworten

Jede Anfrage stumpf mit einem 0x9000 zu beantworten macht im 2.Schritt natürlich wenig Sinn, da es so zu keiner korrekten Kommunikation zwischem dem Smartphone und der Karte kommen wird. Deshalb sollte das Applet besser mit vorkonfigurierten Response-APDU antworten. Hat man die passende NFC-Smartcard zur App parat kann man so im Wechsel eine C-APDU loggen, die C-APDU an die richtige Karte senden, das Applet mit der R-APDU konfigurieren und so Schritt für Schritt quasi die Karte emulieren. Das Unterfangen ist zwar ziemlich mühsam aber für einen Logger unter 20 Euro akzeptabel.

Bei meinen Experimenten hat es sich allerdings herausgestellt, dass es Sinn macht eine Statemachine in das Applet zu implementieren, da je nach Status der Karte Anfragen unterschiedlich beantwortet werden müssen.

Btw: Das Applet kann natürlich auch zum Loggen einer kontaktbehafteten Karte, wie zB der Gesundheitskarte genutzt werden, da es der Karte nahezu egal ist über welches Interface die APDUs gesendet werden. Lesezugriffe auf Mifare Classic bzw ISO14443-3-Level kann mit der JavaCard leider nicht geloggt werden, da die Mifare Kommunikation eine Protokollebene niedriger stattfindet und nicht über die JavaCard API läuft.

Blank 64k Programmable JAVA SIM Card

Blank_64k_Programmable_JAVA_SIM_Card
„Blank 64k Programmable JAVA SIM Card“ so wurde die SIM-Karte bei eBay betitelt. Die musste natürlich bestellt werden, da ich schon ein bisschen mit JavaCards experimentiert habe und die Karte auch nur $5 (~3.70EUR + 2.22EUR Versand) gekostet hat. Erste Tests zeigten allerdings dass es sich hier nicht um eine generische JavaCard handelt, bei der man mit freien Tools (zB gpj, etc) einfach Applets per Cardmanager auf die Karte installieren kann. Diese Karte ist entweder für die Nutzung als SIM-Karte prepersonalisiert oder grundsätzlich nur für diesen Verwendungszweck konzipiert worden:

Hier ein paar Versuche der Karte Daten / R-APDUs zu entlocken:

#ATR auslesen
/atr
3B 9E 96 80 1F 87 80 31 E0 73 FE 21 12 66 55 57 4A 43 30 33 91

#default Applet selektieren (liefert File Control Information (FCI) Template)
/send 00a4040000
=> 00 A4 04 00 00
<= 6F 13 84 0B A0 00 00 00 70 00 05 01 49 53 44 A5
   04 9F 65 01 FF 90 00

#damit kann man den Cardmanager / ISD (mit AID A000000070000501495344) selektieren
/card -a "A0 00 00 00 70 00 05 01 49 53 44"
 <= 6F 13 84 0B A0 00 00 00 70 00 05 01 49 53 44 A5     
 04 9F 65 01 FF 90 00 

#CPLC Daten (alias Tag 9F7F) auslesen
cm> get-cplc
 => 80 CA 9F 7F 00
 <= 6A 88 Status: Reference data not found 

#Card Recognition Data (alias Tag 0066) Auslesen
cm> get-data 0066
 => 80 CA 00 66 00
 <= 6A 88 Status: Reference data not found 

#Key Information Template (alias Tag 0xE0) auslesen möglich?
cm> get-data 00e0
 => 80 CA 00 E0 00
 <= 6A 88
Status: Reference data not found

Anhand der des Cardmanager AIDs (A000000070000501495344) kann man auf den Hersteller bzw den RID (Registered Application Provider Identifier) schliessen:
A000000070; Prism Card Technologies; South Africa zu finden unter http://prism.co.za bzw mitlerweile http://net1.com

Leider unterstützt die Karte keine Authentifizierung durch INITIALIZE UPDATE / EXTERNAL AUTHENTICATE wie es bei JavaCards nach Global Platform 2.x spezifiziert ist um Applets auf die Karte zu laden:

cm> init-update
=> 80 50 00 00 08 60 F3 6D 23 32 2F 2D D4 00
<= 6E 00
Status: CLA value not supported

SIMalliance CAT Loader alias Applet Upload

Mehr Erfolg mit einem Upload eines Applets / CAP Files hat man wie @codebutler im README.md beschreibt:

    Right-click on "Root", "Add Node" -> "Add OTA Session"
        Send Terminal Profile: True
        Right-click on OTASession, "Add Package"
            FileName: (choose cap file)
            Security domain AID: A000000070000501495344
        Right-click on OTASession, "Add Applet STK"
            Package AID: D0D1D2D3D4D601
            AID: D0D1D2D3D4D60101
            Instance AID: D0D1D2D3D4D60101
            Max menu entries: 01
            Menu entries: 0001

    OTA Configuration (toolbar button)
        SMS
            Originating Address / Service centre
                Type of number: International
                NPI: National
                Number: 55667788

Hierfür lädt man sich den SIMalliance CAT Loader V2.0 (nach einer Registrierung) herunter und kann so z.B. das Hello JavaCard Applet auf die Karte via CAT TP (Card Application Toolkit Transport Protocol) installieren.

screenshot-simalliance-loader

AIDs / ISDs / Packages

Folgende Packages sind auf der Karte vorhanden:

 
#vor der Nutzung des SimAlliance Loaders
Packages
A0000000620001                   java.lang
A0000000620101                   javacard.framework
A0000000620102                   javacard.security
A000000070000501495344           Secure Domain
A0000000700005016A637265696E74
A0000000700005016E61746D
A0000000700005015574696C
A000000070000501FFFFFFFF43414C

#nach dem Upload des hello World applets
Packages
A0000000620001                    java.lang
A0000000620101                    javacard.framework
A0000000620102                    javacard.security
A0000000620201                    javacardx.crypto
A0000000090003FFFFFFFF8910710001  sim.access  http://www.andresteder.com/static/api/simtoolkitapi/sim/access/package-summary.html
A0000000090003FFFFFFFF8910710002  sim.toolkit http://www.andresteder.com/static/api/simtoolkitapi/sim/toolkit/package-summary.html
A0000000700005016A637265696E74 
A0000000700005016E61746D 
A0000000700005015574696C 
A000000070000501FFFFFFFF43414C
A0000000700005016A637265
A000000070000501FFFFFFFF43414D
A000000070000503444553
A000000070000503534841
A000000070000503524E47
A000000070000501FFFFFFFF4746324E
A0000000700005017374776962
A0000000700005016A77696269
A0000000700005016A776962
A0000000700170696E
A0000000700005014D617468
A00000015100                   GP Cardmanager / Secure Domain
D0D1D2D3D4D601                 hello world applet package

Applets:
A00000007000050152464D
A000000070000501574942
A000000070000501495344         CardManager/ISD (application privilege: 0x80)
A0000000700005016A63726501
D0D1D2D3D4D60101               hello world applet instance

UPDATE 2013-10-09:

Shadytel SIM Tools

Eine weitere Möglichkeit Applets auf die Karte zu laden ist die Verwendung der Shadytel SIM Tools. Dieses in Python geschriebene Skript verpackt die Upload-APDUs eines CAP-Files in SMS-PP ENVELOPE APDUs. Ausser dem Hochladen können die vorhandenen Packages / Instanzen aufgelistet werden:

user@rena:~/javacard/hello-stk$ ../sim-tools/bin/shadysim --pcsc -t
ICCID: 89XXXXXXXXXXXXXXXXXX
AID: a0000000620001, State: 01, Privs: 00
AID: a0000000620101, State: 01, Privs: 00
AID: a0000000700005016a637265696e74, State: 01, Privs: 00
AID: a0000000700005016e61746d, State: 01, Privs: 00
AID: a0000000700005015574696c, State: 01, Privs: 00
AID: a000000070000501ffffffff43414c, State: 01, Privs: 00
AID: a0000000620102, State: 01, Privs: 00
AID: a0000000620201, State: 01, Privs: 00
AID: a0000000090003ffffffff8910710001, State: 01, Privs: 00
AID: a0000000090003ffffffff8910710002, State: 01, Privs: 00
AID: a0000000700005016a637265, State: 01, Privs: 00
	Instance AID: a0000000700005016a63726501
AID: a000000070000501ffffffff43414d, State: 01, Privs: 00
	Instance AID: a000000070000501ffffffff43414d01
AID: a000000070000503444553, State: 01, Privs: 00
AID: a000000070000503534841, State: 01, Privs: 00
AID: a000000070000503524e47, State: 01, Privs: 00
AID: a000000070000501ffffffff4746324e, State: 01, Privs: 00
AID: a0000000700005017374776962, State: 01, Privs: 00
AID: a0000000700005016a77696269, State: 01, Privs: 00
AID: a0000000700005016a776962, State: 01, Privs: 00
	Instance AID: a0000000700005016a77696201
AID: a00000015100, State: 01, Privs: 00
AID: a0000000700170696e, State: 01, Privs: 00
AID: a0000000700005014d617468, State: 01, Privs: 00
AID: d07002ca449001, State: 01, Privs: 00
	Instance AID: d07002ca44900101

Weitere Infos/Links

Kalixa NFC paypass MasterCard

KalixaCard
Heute kam meine Kalixa Prepaid NFC MasterCard mit der Post. Seit dem Bestellen der Karte war ich schon gespannt was für ein Chip in der Karte eingesetzt wird. Also gleich nach dem Öffnen des Briefs Rechner hochgefahren und mal nachschauen auf welche Daten man zugreifen kann:

kontakt
ATR=3B 68 00 00 00 73 C8 40 11 00 90 00

kontaktlos
ATR=3B 86 80 01 4B 4F 4E 41 14 11 09

#SELECT ohne AID liefert Cardmanager AID A000000003000000 
=> 00 A4 04 00
<= 6F 10 84 08 A0 00 00 00 03 00 00 00 A5 04 9F 65
# => nice scheint eine GP2.1 Karte (AID = A000000003000000) zu sein

#GET DATA Tag 00E0 zeigt Keyinfos an
=> 80 CA 00 E0 00 
<= E0 12 C0 04 01 FF 80 10 C0 04 02 FF 80 10 C0 04 03 FF 80 10 90 00 
Key information: 
Key ID : 1 
Key version : 255 
Key component 1 : 
Type : DES 
Length : 16 bytes 
Key information: 
Key ID : 2 
Key version : 255 
Key component 1 : 
Type : DES 
Length : 16 bytes 
Key information: 
Key ID : 3 
Key version : 255 
Key component 1 : 
Type : DES 
Length : 16 bytes

Verwundert hat mich dann ein wenig, dass die JavaCard noch den Default Key für die Authentifizierung zum CardManager besitzt, sodass man sich die geladenen Applets anzeigen lassen kann:

#INITIALIZE UPDATE
=> 80 50 00 00 08 ...
...

#EXTERNAL AUTHENTICATE
=> 84 82 01 00 10 ...
...

#GET STATUS
=> 84 F2 20 00 0A ...
...

Card Manager AID   :  A000000003000000
Card Manager state :  SECURED

    Application:PERSONALIZED (---L----) A0000000041010
    Application:  SELECTABLE (--------) "2PAY.SYS.DDF01"
    Load File  :      LOADED (--------) A00000000310     (VSDC)
    Load File  :      LOADED (--------) A00000000410
    Load File  :      LOADED (--------) "2PAY.SYS.DDF0"
    Load File  :      LOADED (--------) D410650990001000
    Load File  :      LOADED (--------) D410650990003000
    Load File  :      LOADED (--------) D410650030
    Load File  :      LOADED (--------) D4106401604D4600
    Load File  :      LOADED (--------) A000000078584C50
    Load File  :      LOADED (--------) D41000000301
    Load File  :      LOADED (--------) A00000027710

Das Auslesen der CPLC-Daten liefert

#GET DATA 9F7F
=> 80 CA 9F 7F 00
<= 9F 7F … 90 00
IC Fabricator : 4790
IC Type : 5032
Operating System ID : 8241
Das Hochladen eines eigenen CAP-Files wird allerdings mit Fehler 6A 86 abgebrochen:

#INSTALL FOR LOAD
 => 84 E6 02 00 20 FA 75 F7 86 3C F7 A2 21 AB 43 19
    2E 0F F4 27 1B 31 10 48 E2 6F 69 CA DB D5 53 F5
    73 36 21 31 12 00
 <= 6A 86

Vielleicht weiss jemand wieso 6A86 also ‚Incorrect parameters (P1,P2)‘ ausgegeben wird?

Löschen eines vorhandenen Applets muss ich an dieser Stelle nicht ausprobieren, da ich die Karte ja grade erst neu habe und zumindest erst einmal das vorhandene Guthaben verbrauchen will.

#DELETE AID *lieber nicht*
 => 84 E4 00 00 18 ...
...

Die NFC Daten muss ich mir dann nochmal in Ruhe anschauen…