Im Rahmen unserer Versuche wurden zwei unterschiedliche Smartcards verwendet, um die Kommunikation zwischen Terminal und Chipkarte zu protokollieren:
Javacard: Eine spezielle Form der programmieren Chipkarte ist die Javacard. Diese Karte enthält ein eigenes Betriebssystem, dass die Ausführung von Java-Applikationen ermöglicht. Daher ist es sehr einfach, selbst Applikationen zu schreiben, da keine weitere Hardware wie z.B. Programmer benötigt werden. Allerdings kann eine Javacard nur verwendet werden, um die Kommunikation einer "indirect convention"-Karte mit T0-Verfahren zu protokollieren. Daher funktioniert die Javacard nur für die neueren EMV-fähigen Postcards, die seit Sommer 2006 ausgegeben werden.
Der Quellcode für den Javacard-Logger kann eingesehen werden.
Prozessor-Karte: Die Rohform einer programmierbaren Chipkarte ohne eigenes Betriebssystem, die mit einem entsprechenden Programm zur Protokollierung jeder Chipkarten-Kommunikation genutzt werden kann. Für die Programmierung der Karte ist allerdings spezielle Hardware notwendig - die allerdings nicht sehr teuer ist.
Mit dem folgenden generellen Ablaufschema kann die Kommunikation protokolliert werden:
Schritt | Terminal | Logger | Karte | Beschreibung | |||
1 | Sende Request | → | Das Terminal schickt einen Request an die Logger-Karte | ||||
2 | Suche Request | Die Logger-Karte sucht den Request in der Liste der bekannten Anfragen | |||||
3a | ← | Gefunden: Sende Response |
Ist der Request bekannt, wird die hinterlegte Antwort gesendet | ||||
3b | ← | Unbekannt: Speichere Request Sende OK |
Bei einem unbekannten Request wird dieser gespeichert und dem Terminal ein O.K. signalisiert. Irgendwann wird das Terminal merken, dass etwas nicht stimmt und die Transaktion abbrechen. | ||||
4 → 6 | Abbruch | Das Terminal beendet die Transaktion, weil die Kartenantwort nicht verstanden wurde. Die Logger-Karte wird aus dem Terminal entfernt und der Prozess wird bei Schritt 6 fortgeführt. | |||||
5 → 1 | Wiederhole den Prozess ab Schritt 1 | ||||||
6 | Sende Request | → | Der unbekannte Request wird an die echte Karte gesendet | ||||
7 | ← | Sende Response | Die echte Karte antwortet auf den Request | ||||
8 | Speichere Response | Die zugeordnete Antwort wird auf der Logger-Karte hinterlegt und steht für zukünftige Lookups zur Verfügung. | |||||
9 → 1 | Die Logger-Karte wird wieder in das Terminal eingeführt und der Prozess ab Schritt 1 wiederholt bis die gesamte Kommunikation protokolliert ist. |
Requests und Responses sind Datenpakete variabler Länge; ein Response besteht immer aus einem Statuswort (Fehlercode) und optionalen Daten. Im Fall der Postcard sieht die Kommunikation zum Beispiel so aus:
Terminal (Request) | Smartcard (Response) | Beschreibung |
(Power on) | 3B:65:00:00:02:04:6C:90:00 | Nach der Initialisierung schickt die Karte einen ATR (Answer to reset), der die Karte eindeutig identifiziert. |
BC:B0:09:C0:1C | 08:4D:FF:FF:23:9F:0B:EB:... [9000] | Kartenspeicher wird ausgelesen |
BC:B0:09:F8:04 | 3E:AC:9F:CC [9000] | |
BC:B0:08:E0:1C | 2E:03:30:33:3X:XX:XX:XX:... [9000] | |
BC:B0:09:18:1C | 3X:XX:XX:XX:3X:XX:XX:XX:... [9000] |
Das obige Verfahren funktioniert nur, wenn der gleiche Request immer den gleichen Response liefert. Dies ist aber nicht immer der Fall: Der Zugriff auf geschützten Speicher ist erst nach Eingabe einer PIN möglich; ein Zugriffsversuch ohne PIN liefert einen Fehler. Am Beispiel der Postcard sieht das dann so aus:
Terminal (Request) | Smartcard (Response) | Beschreibung |
BC:B0:08:B0:04 | [6A81] | Der versuchte Zugriff auf geschützen Speicher ohne PIN erzeugt einen Fehlercode |
BC:20:00:00:04:XX:XX:XX:XX | [9000] | Übermittlung der PIN an die Karte zur Freischaltung |
BC:40:00:00:00 | [9000] | |
BC:B0:08:B0:04 | 75:XX:XX:XX [9000] | Der gleiche Request liefert jetzt Daten |
Das Logging-Verfahren muss also zusätzlich eine Zustands-Variable verwenden, damit auch oben aufgeführte Kommunikation korrekt abgebildet werden kann. Jede Zustandsänderung selbst wird dabei durch definierte Requests ausgelöst und muss aus der geloggten Kommunikation ermittelt werden.
Die verwendeten Datenstrukturen für Requests und Responses in unserer Logging-Applikation haben deshalb folgendes Format, mit dem ein stateful lookup realisiert werden kann:
Offset | Länge | Feld | Beschreibung |
0x00 | 1 | Index | Der Index wird verwendet, um Requests zu identifizieren und den zugeordneten Eintrag in der Response-Liste zu ermitteln. Die Liste wird durch den Index 0 beendet. |
0x01 | 1 | State | Jeder Request kennt den Zustandswert, in dem er auftreten kann. Gleiche Requests in unterschiedlichen Zuständen sind unterschiedliche Einträge in dieser Liste. Ist der Zustand irrelevant, dann wird der Zustandswert 0 verwendet. |
0x02 | 1 | Transition | Gibt an, in welchen Zustand das Logging wechselt wenn der entsprechende Request empfangen wird. Ein Wert von -1 (0xFF) bedeutet, dass kein Zustandswechsel erfolgt. |
0x03 | 1 | Size | Dieses Feld gibt an, wieviele zusätzliche Daten mit dem Request verarbeitet werden müssen. |
0x04 | 5 | APDU | Dieersten fünf Bytes des Requests (Mindestlänge). |
0x09 | <Size> | Data | Zusätzliche Daten des Requests |
Offset | Länge | Feld | Beschreibung |
0x00 | 1 | Index | Der Index wird verwendet, um Responses den entsprechenden Requests zuzuordnen. Die Liste wird durch den Index 0 beendet. |
0x01 | 1 | Type | Der Typ beschreibt, ob der Response nur aus einem Statusword (Type = 1) oder zusätzlichen Daten (Type = 2, erzwingt Statusword O.K.) besteht. |
0x02 | 2 | Result | Bei einem Type=1 Response enthält dieses Feld das Statusword der Antwort; bei einem Type=2 Response steht hier die Länge der nachfolgenden Daten. |
0x04 | <Result> | Data | Optional: Bei Type=2 Response finden sich hier die Antwort-Daten. |
Wie sich die bisherigen Teile zu einem Ganzen zusammensetzen, kann anhand des Javacard-Loggers nachvollzogen werden.