Hostbasierte Kartenemulation – Übersicht

Viele Android-Geräte mit NFC-Funktion unterstützen die NFC-Kartenemulation bereits. In den meisten Fällen wird die Karte durch einen separaten Chip auf dem Gerät emuliert, der als Secure Element bezeichnet wird. Viele SIM-Karten von Mobilfunkanbietern enthalten ebenfalls ein Secure Element.

Android 4.4 und höher bieten eine zusätzliche Methode der Kartenemulation, die kein Secure Element beinhaltet: die hostbasierte Kartenemulation. So kann jede Android-App eine Karte emulieren und direkt mit dem NFC-Lesegerät kommunizieren. In diesem Thema wird beschrieben, wie die hostbasierte Kartenemulation (HCE) unter Android funktioniert und wie Sie eine App entwickeln können, die mit dieser Methode eine NFC-Karte emuliert.

Kartenemulation mit einem Secure Element

Wenn die NFC-Kartenemulation über ein Secure Element bereitgestellt wird, wird die zu emulierende Karte über eine Android-Anwendung im Secure Element auf dem Gerät bereitgestellt. Wenn der Nutzer das Gerät dann an ein NFC-Terminal hält, leitet der NFC-Controller auf dem Gerät alle Daten vom Lesegerät direkt an das Secure Element weiter. Abbildung 1 veranschaulicht dieses Konzept:

Ein Diagramm mit einem NFC-Leser, der über einen NFC-Controller Informationen aus einem sicheren Element abruft
Abbildung 1: NFC-Kartenemulation mit einem Secure Element.

Das Secure Element selbst führt die Kommunikation mit dem NFC-Terminal aus und es ist keine Android-Anwendung an der Transaktion beteiligt. Nach Abschluss der Transaktion kann eine Android-Anwendung das Secure Element direkt nach dem Transaktionsstatus fragen und den Nutzer benachrichtigen.

Hostbasierte Kartenemulation

Wenn eine NFC-Karte mithilfe der hostbasierten Kartenemulation emuliert wird, werden die Daten direkt an die Host-CPU und nicht an ein Secure Element weitergeleitet. Abbildung 2 zeigt, wie die hostbasierte Kartenemulation funktioniert:

Diagramm mit einem NFC-Lesegerät, das über einen NFC-Controller Informationen von der CPU abruft
Abbildung 2: NFC-Kartenemulation ohne Secure Element.

Unterstützte NFC-Karten und ‑Protokolle

Diagramm mit dem HCE-Protokollstapel
Abbildung 3: HCE-Protokoll-Stack von Android

Die NFC-Standards unterstützen viele verschiedene Protokolle und es gibt verschiedene Arten von Karten, die Sie emulieren können.

Android 4.4 und höher unterstützen mehrere Protokolle, die heute auf dem Markt üblich sind. Viele vorhandene kontaktlose Karten basieren bereits auf diesen Protokollen, z. B. kontaktlose Zahlungskarten. Diese Protokolle werden auch von vielen NFC-Lesegeräten auf dem Markt unterstützt, einschließlich Android-NFC-Geräten, die selbst als Lesegeräte fungieren (siehe Klasse IsoDep). So können Sie eine End-to-End-NFC-Lösung für HCE mit ausschließlich Android-Geräten erstellen und bereitstellen.

Insbesondere werden mit Android 4.4 und höher Karten emuliert, die auf der ISO-DEP-Spezifikation des NFC-Forums (basierend auf ISO/IEC 14443-4) basieren und Application Protocol Data Units (APDUs) gemäß der ISO/IEC 7816-4-Spezifikation verarbeiten. Android erfordert die Emulation von ISO-DEP nur über die NFC-A-Technologie (ISO/IEC 14443-3 Typ A). Die Unterstützung der NFC-B-Technologie (ISO/IEC 14443-4 Typ B) ist optional. Abbildung 3 zeigt die Schichtung all dieser Spezifikationen.

HCE-Dienste

Die HCE-Architektur in Android basiert auf Android-Service-Komponenten (HCE-Dienste). Einer der Hauptvorteile eines Dienstes besteht darin, dass er ohne Benutzeroberfläche im Hintergrund ausgeführt werden kann. Das ist eine gute Lösung für viele HCE-Anwendungen wie Kundenkarten oder Fahrkarten, für die der Nutzer keine App starten muss. Stattdessen wird durch das Anhalten des Geräts an den NFC-Leser der richtige Dienst gestartet, falls er noch nicht ausgeführt wird, und die Transaktion wird im Hintergrund ausgeführt. Natürlich können Sie bei Bedarf zusätzliche UI-Elemente (z. B. Nutzerbenachrichtigungen) über Ihren Dienst starten.

Dienstauswahl

Wenn der Nutzer ein Gerät an einen NFC-Leser hält, muss das Android-System wissen, mit welchem HCE-Dienst der NFC-Leser kommunizieren möchte. Die ISO/IEC 7816-4-Spezifikation definiert eine Methode zur Auswahl von Anwendungen, die sich um eine Anwendungs-ID (Application ID, AID) dreht. Eine AID besteht aus bis zu 16 Byte. Wenn Sie Karten für eine vorhandene NFC-Leserinfrastruktur emulieren, sind die AIDs, nach denen diese Leser suchen, in der Regel bekannt und öffentlich registriert (z. B. die AIDs von Zahlungsnetzwerken wie Visa und MasterCard).

Wenn Sie eine neue Leseinfrastruktur für Ihre eigene Anwendung bereitstellen möchten, müssen Sie Ihre eigenen AIDs registrieren. Das Registrierungsverfahren für AIDs ist in der ISO/IEC 7816-5-Spezifikation definiert. Wir empfehlen, eine AID gemäß 7816-5 zu registrieren, wenn Sie eine HCE-Anwendung für Android bereitstellen, da so Kollisionen mit anderen Anwendungen vermieden werden.

AID-Gruppen

In einigen Fällen muss ein HCE-Dienst möglicherweise mehrere AIDs registrieren und als Standard-Handler für alle AIDs festgelegt werden, um eine bestimmte Anwendung zu implementieren. Einige AIDs in der Gruppe, die zu einem anderen Dienst weitergeleitet werden, werden nicht unterstützt.

Eine Liste von AIDs, die zusammengehalten werden, wird als AID-Gruppe bezeichnet. Für alle AIDs in einer AID-Gruppe garantiert Android Folgendes:

  • Alle AIDs in der Gruppe werden an diesen HCE-Dienst weitergeleitet.
  • Keine AIDs in der Gruppe werden an diesen HCE-Dienst weitergeleitet (z. B. weil der Nutzer einen anderen Dienst bevorzugt hat, für den auch eine oder mehrere AIDs in Ihrer Gruppe angefordert wurden).

Mit anderen Worten: Es gibt keinen Zwischenstatus, bei dem einige AIDs in der Gruppe an einen HCE-Dienst und andere an einen anderen weitergeleitet werden können.

AID-Gruppen und ‑Kategorien

Sie können jeder AID-Gruppe eine Kategorie zuweisen. So können HCE-Dienste in Android nach Kategorie gruppiert werden. Dadurch kann der Nutzer Standardeinstellungen auf Kategorieebene statt auf AID-Ebene festlegen. Erwähnen Sie AIDs nicht in nutzerorientierten Bereichen Ihrer App, da sie für den durchschnittlichen Nutzer keine Bedeutung haben.

Android 4.4 und höher unterstützt zwei Kategorien:

HCE-Dienst implementieren

Wenn Sie eine NFC-Karte mithilfe der hostbasierten Kartenemulation emulieren möchten, müssen Sie eine Service-Komponente erstellen, die die NFC-Transaktionen verarbeitet.

HCE-Unterstützung prüfen

Ihre Anwendung kann prüfen, ob ein Gerät HCE unterstützt, indem sie nach der Funktion FEATURE_NFC_HOST_CARD_EMULATION sucht. Verwenden Sie das Tag <uses-feature> im Manifest Ihrer Anwendung, um anzugeben, dass Ihre App die HCE-Funktion verwendet und ob sie für die Funktion der App erforderlich ist.

Dienstimplementierung

Android 4.4 und höher bietet eine praktische Service-Klasse, die Sie als Grundlage für die Implementierung eines HCE-Dienstes verwenden können: die Klasse HostApduService.

Im ersten Schritt wird HostApduService erweitert, wie im folgenden Codebeispiel gezeigt:

Kotlin

class MyHostApduService : HostApduService() {

    override fun processCommandApdu(commandApdu: ByteArray, extras: Bundle?): ByteArray {
       ...
    }

    override fun onDeactivated(reason: Int) {
       ...
    }
}

Java

public class MyHostApduService extends HostApduService {
    @Override
    public byte[] processCommandApdu(byte[] apdu, Bundle extras) {
       ...
    }
    @Override
    public void onDeactivated(int reason) {
       ...
    }
}

HostApduService deklariert zwei abstrakte Methoden, die Sie überschreiben und implementieren müssen. Eine davon, processCommandApdu(), wird aufgerufen, wenn ein NFC-Lesegerät eine Application Protocol Data Unit (APDU) an Ihren Dienst sendet. APDUs sind in der ISO/IEC 7816-4-Spezifikation definiert. APDUs sind die Pakete auf Anwendungsebene, die zwischen dem NFC-Lesegerät und Ihrem HCE-Dienst ausgetauscht werden. Dieses Protokoll auf Anwendungsebene ist halbduplex: Der NFC-Leser sendet Ihnen eine Befehls-APDU und wartet darauf, dass Sie eine Antwort-APDU zurücksenden.

Wie bereits erwähnt, verwendet Android die AID, um zu ermitteln, mit welchem HCE-Dienst der Leser kommunizieren möchte. Normalerweise ist die erste APDU, die ein NFC-Lesegerät an Ihr Gerät sendet, eine SELECT AID APDU. Diese APDU enthält die AID, mit der der Leser kommunizieren möchte. Android extrahiert diese AID aus der APDU, löst sie in einen HCE-Dienst auf und leitet die APDU dann an den aufgelösten Dienst weiter.

Sie können eine Antwort-APDU senden, indem Sie die Bytes der Antwort-APDU von processCommandApdu() zurückgeben. Diese Methode wird im Hauptthread Ihrer Anwendung aufgerufen, den Sie nicht blockieren sollten. Wenn Sie eine Antwort-APDU nicht sofort berechnen und zurückgeben können, geben Sie „null“ zurück. Sie können dann die erforderlichen Arbeiten in einem anderen Thread ausführen und die in der Klasse HostApduService definierte Methode sendResponseApdu() verwenden, um die Antwort zu senden, wenn Sie fertig sind.

Android leitet neue APDUs vom Lesegerät an Ihren Dienst weiter, bis eines der folgenden Ereignisse eintritt:

  • Der NFC-Leser sendet eine weitere SELECT AID-APDU, die vom Betriebssystem auf einen anderen Dienst aufgelöst wird.
  • Die NFC-Verbindung zwischen dem NFC-Lesegerät und Ihrem Gerät ist unterbrochen.

In beiden Fällen wird die onDeactivated()-Implementierung Ihrer Klasse mit einem Argument aufgerufen, das angibt, welcher der beiden Fälle eingetreten ist.

Wenn Sie mit einer vorhandenen Lesegeräteinfrastruktur arbeiten, müssen Sie das vorhandene Protokoll auf Anwendungsebene implementieren, das die Lesegeräte in Ihrem HCE-Dienst erwarten.

Wenn Sie eine neue Leserinfrastruktur bereitstellen, die Sie auch steuern, können Sie Ihr eigenes Protokoll und Ihre eigene APDU-Sequenz definieren. Begrenzen Sie die Anzahl der APDUs und die Größe der auszutauschenden Daten. So müssen Nutzer ihr Gerät nur kurz über den NFC-Leser halten. Eine angemessene Obergrenze liegt bei etwa 1 KB Daten, die in der Regel innerhalb von 300 ms ausgetauscht werden können.

Erklärung zum Servicemanifest und AID-Registrierung

Sie müssen Ihren Dienst wie gewohnt im Manifest deklarieren, aber auch einige zusätzliche Elemente zur Dienstdeklaration hinzufügen:

  1. Wenn Sie der Plattform mitteilen möchten, dass es sich um einen HCE-Dienst handelt, der eine HostApduService-Oberfläche implementiert, fügen Sie Ihrer Dienstdeklaration einen Intent-Filter für die Aktion SERVICE_INTERFACE hinzu.

  2. Wenn Sie der Plattform mitteilen möchten, welche AID-Gruppen von diesem Dienst angefordert werden, fügen Sie der Deklaration des Dienstes das Tag SERVICE_META_DATA <meta-data> hinzu, das auf eine XML-Ressource mit zusätzlichen Informationen zum HCE-Dienst verweist.

  3. Legen Sie das android:exported-Attribut auf true fest und fordern Sie in Ihrer Diensterklärung die Berechtigung android.permission.BIND_NFC_SERVICE an. Ersteres sorgt dafür, dass der Dienst von externen Anwendungen gebunden werden kann. Letzteres erzwingt dann, dass nur externe Anwendungen, die die Berechtigung android.permission.BIND_NFC_SERVICE haben, an Ihren Dienst gebunden werden können. Da android.permission.BIND_NFC_SERVICE eine Systemberechtigung ist, kann nur das Android-Betriebssystem eine Bindung an Ihren Dienst vornehmen.

Das folgende Beispiel zeigt eine Manifestdeklaration für HostApduService:

<service android:name=".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>

Dieses Metadaten-Tag verweist auf eine apduservice.xml-Datei. Im Folgenden finden Sie ein Beispiel für eine solche Datei mit einer einzelnen AID-Gruppendeklaration, die zwei proprietäre AIDs enthält:

<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
           android:description="@string/servicedesc"
           android:requireDeviceUnlock="false">
    <aid-group android:description="@string/aiddescription"
               android:category="other">
        <aid-filter android:name="F0010203040506"/>
        <aid-filter android:name="F0394148148100"/>
    </aid-group>
</host-apdu-service>

Das <host-apdu-service>-Tag muss das Attribut <android:description> enthalten, das eine nutzerfreundliche Beschreibung des Dienstes enthält, die in der App-Benutzeroberfläche angezeigt werden kann. Mit dem Attribut requireDeviceUnlock können Sie angeben, dass das Gerät entsperrt ist, bevor Sie diesen Dienst zum Bearbeiten von APDUs aufrufen.

Das <host-apdu-service>-Element muss mindestens ein <aid-group>-Tag enthalten. Für jedes <aid-group>-Tag gilt Folgendes:

  • Sie müssen ein android:description-Attribut enthalten, das eine nutzerfreundliche Beschreibung der AID-Gruppe enthält, die für die Anzeige auf der Benutzeroberfläche geeignet ist.
  • Das android:category-Attribut muss so festgelegt sein, dass die Kategorie der AID-Gruppe angegeben wird, z. B. die Stringkonstanten, die durch CATEGORY_PAYMENT oder CATEGORY_OTHER definiert sind.
  • Sie enthalten ein oder mehrere <aid-filter>-Tags, die jeweils eine einzelne AID enthalten. Geben Sie die AID im Hexadezimalformat an und achten Sie darauf, dass sie eine gerade Anzahl von Zeichen enthält.

Ihre Anwendung muss außerdem die Berechtigung NFC haben, um sich als HCE-Dienst zu registrieren.

Konfliktlösung für AID

Auf einem einzelnen Gerät können mehrere HostApduService-Komponenten installiert sein und dieselbe AID kann von mehreren Diensten registriert werden. Android bestimmt anhand der folgenden Schritte, welcher Dienst aufgerufen werden soll:

  1. Wenn die ausgewählte Standard-Wallet-App des Nutzers die AID registriert hat, wird diese App aufgerufen.
  2. Wenn die Standard-Wallet-App die AID nicht registriert hat, wird der Dienst aufgerufen, der die AID registriert hat.
  3. Wenn die AID von mehreren Diensten registriert wurde, wird der Nutzer von Android gefragt, welchen Dienst er aufrufen möchte.

Prüfen, ob Ihre App die Standard-Wallet-App ist

Apps können prüfen, ob sie die Standard-Wallet-App sind, indem sie RoleManager.ROLE_WALLET an RoleManager.isRoleHeld() übergeben.

Wenn Ihre App nicht die Standard-Wallet-App ist, können Sie die Standard-Wallet-Rolle anfordern, indem Sie RoleManager.ROLE_WALLET an RoleManager.createRequestRoleIntent() übergeben.

Wallet-Apps

Android betrachtet HCE-Dienste, die eine AID-Gruppe mit der Zahlungskategorie deklariert haben, als Wallet-Anwendungen. Android 15 und höher enthält eine Standardrolle für Wallet-Apps, die Nutzer unter Einstellungen > Apps > Standard-Apps auswählen können. Hier wird die Standard-Wallet-App definiert, die aufgerufen wird, wenn ein Zahlungsterminal angetippt wird.

Erforderliche Assets für Wallet-Apps

Für eine visuell ansprechendere Nutzererfahrung müssen HCE-Wallet-Apps ein Servicebanner enthalten.

Android 13 oder höher

Passen Sie die Banneranforderung an ein quadratisches Symbol an, damit es besser in die Standardauswahlliste für Zahlungen in der Benutzeroberfläche der Einstellungen passt. Idealerweise sollte es mit dem Design des App Launcher-Symbols identisch sein. Durch diese Anpassung wird für mehr Einheitlichkeit und ein klareres Erscheinungsbild gesorgt.

Android 12 und niedriger

Legen Sie die Größe des Dienstbanners auf 260 × 96 dp fest und legen Sie dann die Größe des Dienstbanners in Ihrer Metadaten-XML-Datei fest, indem Sie dem Tag <host-apdu-service>, das auf die drawable-Ressource verweist, das Attribut android:apduServiceBanner hinzufügen. Hier ein Beispiel:

<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
        android:description="@string/servicedesc"
        android:requireDeviceUnlock="false"
        android:apduServiceBanner="@drawable/my_banner">
    <aid-group android:description="@string/aiddescription"
               android:category="payment">
        <aid-filter android:name="F0010203040506"/>
        <aid-filter android:name="F0394148148100"/>
    </aid-group>
</host-apdu-service>

Beobachtungsmodus

Mit Android 15 wird der Beobachtungsmodus eingeführt. Wenn der Beobachtungsmodus aktiviert ist, kann das Gerät NFC-Abfrageschleifen beobachten und Benachrichtigungen dazu an die entsprechenden HostApduService-Komponenten senden, damit sie sich auf die Interaktion mit einem bestimmten NFC-Terminal vorbereiten können. Ein HostApduService kann das Gerät in den Beobachtungsmodus versetzen, indem es true an setObserveModeEnabled() übergibt. Dadurch wird der NFC-Stack angewiesen, keine NFC-Transaktionen zuzulassen und stattdessen Polling-Schleifen passiv zu beobachten.

Filter für Polling-Schleifen

Sie können Polling-Loop-Filter für eine HostApduService mit einer der folgenden Methoden registrieren:

Wenn ein Polling-Loop-Filter mit nicht standardmäßigen Polling-Frames übereinstimmt, leitet der NFC-Stack diese Polling-Frames an die entsprechende HostApduService weiter, indem er die Methode processPollingFrames() aufruft. So kann der Dienst alle erforderlichen Schritte ausführen, um sicherzustellen, dass der Nutzer bereit ist, eine Transaktion auszuführen, und dies auch beabsichtigt, z. B. durch Authentifizierung des Nutzers. Wenn ein NFC-Leser nur Standardframes in seinem Polling-Loop verwendet, leitet der NFC-Stack diese Polling-Frames an den bevorzugten Dienst im Vordergrund weiter, wenn sich dieser Dienst im Vordergrund befindet, andernfalls an den Standardinhaber der Wallet-Rolle.

Polling-Frame-Benachrichtigungen enthalten auch eine anbieterspezifische Messung der Feldstärke, die Sie durch Aufrufen von getVendorSpecificGain() abrufen können. Anbieter können Messungen mit ihrer eigenen Skala bereitstellen, solange sie in ein einzelnes Byte passen.

Auf Polling-Schleifen reagieren und den Beobachtungsmodus beenden

Wenn der Dienst für Transaktionen bereit ist, kann er den Beobachtungsmodus beenden, indem er false an setObserveModeEnabled() übergibt. Der NFC-Stack lässt dann Transaktionen zu.

HostApduService-Komponenten können angeben, dass der Beobachtungsmodus aktiviert werden soll, wenn sie der bevorzugte Zahlungsdienst sind. Dazu müssen sie im Manifest shouldDefaultToObserveMode auf true setzen oder CardEmulation.setShouldDefaultToObserveModeForService() aufrufen.

Mit den Komponenten HostApduService und OffHostApduService können Sie auch angeben, dass Polling-Loop-Filter, die mit empfangenen Polling-Loop-Frames übereinstimmen, den Beobachtungsmodus automatisch deaktivieren und Transaktionen fortsetzen sollen. Dazu müssen Sie in der PollingLoopFilter-Deklaration im Manifest autoTransact auf true festlegen.

Verhalten bei ausgeschaltetem Display und Sperrbildschirm

Das Verhalten von HCE-Diensten hängt von der Android-Version ab, die auf dem Gerät ausgeführt wird.

Android 12 und höher

In Apps, die auf Android 12 (API-Level 31) und höher ausgerichtet sind, können Sie NFC-Zahlungen aktivieren, ohne dass das Display des Geräts eingeschaltet ist. Legen Sie dazu requireDeviceScreenOn auf false fest.

Android 10 und höher

Geräte mit Android 10 (API-Level 29) oder höher unterstützen Secure NFC. Wenn sichere NFC aktiviert ist, sind alle Kartenemulatoren (Host- und Off-Host-Anwendungen) nicht verfügbar, wenn das Display des Geräts ausgeschaltet ist. Wenn sichere NFC deaktiviert ist, sind Off-Host-Anwendungen verfügbar, wenn das Display des Geräts ausgeschaltet ist. Sie können mit isSecureNfcSupported() prüfen, ob sichere NFC unterstützt wird.

Auf Geräten mit Android 10 und höher gilt für die Einstellung von android:requireDeviceUnlock auf true dieselbe Funktionalität wie auf Geräten mit Android 9 und niedriger, aber nur, wenn Secure NFC deaktiviert ist. Wenn Secure NFC aktiviert ist, können HCE-Dienste unabhängig von der Einstellung von android:requireDeviceUnlock nicht über den Sperrbildschirm funktionieren.

Android 9 und niedriger

Auf Geräten mit Android 9 (API-Ebene 28) und niedriger werden der NFC-Controller und der Anwendungsprozessor vollständig deaktiviert, wenn das Display des Geräts ausgeschaltet ist. HCE-Dienste funktionieren daher nicht, wenn das Display ausgeschaltet ist.

Auch unter Android 9 und niedriger können HCE-Dienste über den Sperrbildschirm funktionieren. Dies wird jedoch durch das Attribut android:requireDeviceUnlock im <host-apdu-service>-Tag Ihres HCE-Dienstes gesteuert. Standardmäßig ist das Entsperren des Geräts nicht erforderlich und Ihr Dienst wird auch dann aufgerufen, wenn das Gerät gesperrt ist.

Wenn Sie das Attribut android:requireDeviceUnlock für Ihren HCE-Dienst auf true festlegen, wird der Nutzer von Android aufgefordert, das Gerät zu entsperren, wenn Folgendes geschieht:

  • der Nutzer ein NFC-Lesegerät antippt.
  • Der NFC-Leser wählt eine AID aus, die auf Ihren Dienst verweist.

Nach dem Entsperren wird auf Android-Geräten ein Dialogfeld angezeigt, in dem der Nutzer aufgefordert wird, noch einmal zu tippen, um die Transaktion abzuschließen. Das ist notwendig, da der Nutzer das Gerät möglicherweise vom NFC-Lesegerät weg bewegt hat, um es zu entsperren.

Koexistenz mit Secure Element-Karten

Dieser Abschnitt ist für Entwickler interessant, die eine Anwendung bereitgestellt haben, die für die Kartenemulation auf ein Secure Element angewiesen ist. Die HCE-Implementierung von Android ist so konzipiert, dass sie parallel zu anderen Methoden zur Implementierung der Kartenemulation funktioniert, einschließlich der Verwendung von Secure Elements.

Diese Koexistenz basiert auf dem Prinzip des AID-Routings. Der NFC-Controller verwaltet eine Routingtabelle, die aus einer (endlichen) Liste von Routingregeln besteht. Jede Routingregel enthält eine AID und ein Ziel. Das Ziel kann entweder die Host-CPU sein, auf der Android-Apps ausgeführt werden, oder ein verbundenes sicheres Element.

Wenn der NFC-Leser eine APDU mit einer SELECT AID sendet, analysiert der NFC-Controller sie und prüft, ob die AIDs mit einer AID in der Routingtabelle übereinstimmen. Wenn sie übereinstimmen, werden diese APDU und alle nachfolgenden APDUs an das mit der AID verknüpfte Ziel gesendet, bis eine weitere SELECT AID-APDU empfangen wird oder die NFC-Verbindung unterbrochen wird.

Abbildung 4 zeigt diese Architektur:

Diagramm mit NFC-Lesegerät, das sowohl mit einem sicheren Element als auch mit der CPU kommuniziert
Abbildung 4: Android-Betriebssystem, das sowohl mit Secure Element als auch mit Host-Kartenemulation funktioniert

Der NFC-Controller enthält in der Regel auch eine Standardroute für APDUs. Wenn eine AID in der Routingtabelle nicht gefunden wird, wird die Standardroute verwendet. Diese Einstellung kann sich von Gerät zu Gerät unterscheiden. Bei Android-Geräten muss jedoch sichergestellt sein, dass die von Ihrer App registrierten AIDs korrekt an den Host weitergeleitet werden.

Bei Android-Anwendungen, die einen HCE-Dienst implementieren oder ein Secure Element verwenden, müssen Sie sich nicht um die Konfiguration der Routingtabelle kümmern. Das wird von Android automatisch erledigt. Android muss lediglich wissen, welche AIDs von HCE-Diensten und welche vom Secure Element verarbeitet werden können. Die Routingtabelle wird automatisch anhand der installierten Dienste und der vom Nutzer als bevorzugt konfigurierten Dienste konfiguriert.

Im folgenden Abschnitt wird erläutert, wie Sie AIDs für Anwendungen deklarieren, die ein Secure Element für die Kartenemulation verwenden.

AID-Registrierung für Secure Element

Anwendungen, die ein Secure Element für die Kartenemulation verwenden, können in ihrem Manifest einen Off-Host-Dienst deklarieren. Die Erklärung eines solchen Dienstes ist fast identisch mit der Erklärung eines HCE-Dienstes. Es gelten folgende Ausnahmen:

  • Die im Intent-Filter verwendete Aktion muss auf SERVICE_INTERFACE festgelegt sein.
  • Das Metadaten-Namenattribut muss auf SERVICE_META_DATA festgelegt sein.
  • Die Metadaten-XML-Datei muss das Stamm-<offhost-apdu-service>-Tag verwenden.

    <service android:name=".MyOffHostApduService" android:exported="true"
           android:permission="android.permission.BIND_NFC_SERVICE">
      <intent-filter>
          <action android:name="android.nfc.cardemulation.action.OFF_HOST_APDU_SERVICE"/>
      </intent-filter>
      <meta-data android:name="android.nfc.cardemulation.off_host_apdu_service"
                 android:resource="@xml/apduservice"/>
    </service>
    

Im Folgenden finden Sie ein Beispiel für die entsprechende apduservice.xml-Datei, in der zwei AIDs registriert sind:

<offhost-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
           android:description="@string/servicedesc">
    <aid-group android:description="@string/subscription" android:category="other">
        <aid-filter android:name="F0010203040506"/>
        <aid-filter android:name="F0394148148100"/>
    </aid-group>
</offhost-apdu-service>

Das Attribut android:requireDeviceUnlock gilt nicht für Off-Host-Dienste, da die Host-CPU nicht an der Transaktion beteiligt ist und daher nicht verhindern kann, dass das Secure Element Transaktionen ausführt, wenn das Gerät gesperrt ist.

Das Attribut android:apduServiceBanner ist für Off-Host-Dienste erforderlich, die Zahlungsanwendungen sind und als Standard-Zahlungsanwendung ausgewählt werden können.

Aufruf von Diensten außerhalb des Hosts

Android startet oder bindet niemals einen Dienst, der als „off-host“ deklariert ist, da die tatsächlichen Transaktionen vom Secure Element und nicht vom Android-Dienst ausgeführt werden. Die Dienstdeklaration ermöglicht es Anwendungen lediglich, AIDs zu registrieren, die sich auf dem Secure Element befinden.

HCE und Sicherheit

Die HCE-Architektur bietet einen wichtigen Sicherheitsaspekt: Da Ihr Dienst durch die Systemberechtigung BIND_NFC_SERVICE geschützt ist, kann nur das Betriebssystem eine Bindung an Ihren Dienst herstellen und mit ihm kommunizieren. So wird sichergestellt, dass jede empfangene APDU tatsächlich eine APDU ist, die vom Betriebssystem vom NFC-Controller empfangen wurde, und dass jede zurückgesendete APDU nur an das Betriebssystem gesendet wird, das die APDUs wiederum direkt an den NFC-Controller weiterleitet.

Die letzte verbleibende Frage ist, woher Sie die Daten erhalten, die Ihre App an den NFC-Leser sendet. Im HCE-Design ist dies bewusst voneinander getrennt. Es spielt keine Rolle, woher die Daten stammen, es wird nur dafür gesorgt, dass sie sicher an den NFC-Controller und an den NFC-Leser übertragen werden.

Zum sicheren Speichern und Abrufen der Daten, die Sie über Ihren HCE-Dienst senden möchten, können Sie beispielsweise die Android Application Sandbox verwenden, die die Daten Ihrer App von anderen Apps isoliert. Weitere Informationen zur Sicherheit bei Android finden Sie unter Sicherheitstipps.

Protokollparameter und ‑details

Dieser Abschnitt ist für Entwickler von Interesse, die wissen möchten, welche Protokollparameter HCE-Geräte während der Anti-Collision- und Aktivierungsphasen der NFC-Protokolle verwenden. So lässt sich eine Lesegeräteinfrastruktur erstellen, die mit Android-HCE-Geräten kompatibel ist.

Anti-Collision- und Aktivierungsprotokoll für NFC-A (ISO/IEC 14443 Typ A)

Im Rahmen der Aktivierung des Nfc-A-Protokolls werden mehrere Frames ausgetauscht.

Im ersten Teil des Austauschs gibt das HCE-Gerät seine UID an. HCE-Geräte sollten eine zufällige UID haben. Das bedeutet, dass bei jedem Tippen dem Leser eine zufällig generierte UID angezeigt wird. Aus diesem Grund sollten NFC-Lesegeräte nicht auf die UID von HCE-Geräten als Form der Authentifizierung oder Identifizierung angewiesen sein.

Der NFC-Leser kann das HCE-Gerät anschließend durch Senden eines SEL_REQ-Befehls auswählen. In der SEL_RES-Antwort des HCE-Geräts ist mindestens das 6. Bit (0x20) gesetzt, was bedeutet, dass das Gerät ISO-DEP unterstützt. Andere Bits in der SEL_RES können ebenfalls gesetzt sein, was beispielsweise die Unterstützung des NFC-DEP-Protokolls (p2p) angibt. Da andere Bits gesetzt sein können, sollten Lesegeräte, die mit HCE-Geräten interagieren möchten, nur explizit das sechste Bit prüfen und nicht die gesamte SEL_RES mit einem Wert von 0x20 vergleichen.

ISO-DEP-Aktivierung

Nachdem das NFC-A-Protokoll aktiviert wurde, initiiert der NFC-Leser die Aktivierung des ISO-DEP-Protokolls. Es wird ein RATS-Befehl (Request for Answer To Select) gesendet. Der NFC-Controller generiert die RATS-Antwort, die ATS. Die ATS kann nicht von HCE-Diensten konfiguriert werden. HCE-Implementierungen müssen jedoch die NFC Forum-Anforderungen für die ATS-Antwort erfüllen. NFC-Lesegeräte können also davon ausgehen, dass diese Parameter für jedes HCE-Gerät gemäß den NFC Forum-Anforderungen festgelegt sind.

Im folgenden Abschnitt finden Sie weitere Informationen zu den einzelnen Byte der ATS-Antwort, die vom NFC-Controller auf einem HCE-Gerät bereitgestellt wird:

  • TL: Länge der ATS-Antwort. Die Länge darf nicht größer als 20 Byte sein.
  • T0: Bits 5, 6 und 7 müssen auf allen HCE-Geräten gesetzt sein, was bedeutet, dass TA(1), TB(1) und TC(1) in der ATS-Antwort enthalten sind. Die Bits 1 bis 4 geben den FSCI an, der die maximale Framegröße codiert. Auf HCE-Geräten muss der Wert von FSCI zwischen 0 und 8 Stunden liegen.
  • T(A)1: definiert die Bitrate zwischen Lesegerät und Emulator und ob sie asymmetrisch sein kann. Für HCE-Geräte gelten keine Bitratenanforderungen oder -garantien.
  • T(B)1: Bits 1 bis 4 geben die Ganzzahl für die Start Frame Guard Time (SFGI) an. Auf HCE-Geräten muss die SFGI <= 8 Stunden betragen. Die Bits 5 bis 8 geben die Frame-Wartezeit-Ganzzahl (Frame Waiting Time Integer, FWI) an und codieren die Frame-Wartezeit (Frame Waiting Time, FWT). Auf HCE-Geräten muss die FWI <= 8 Stunden betragen.
  • T(C)1: Bit 5 gibt die Unterstützung für „Erweiterte Protokollfunktionen“ an. HCE-Geräte unterstützen möglicherweise erweiterte Protokollfunktionen. Bit 2 gibt die Unterstützung für DID an. HCE-Geräte unterstützen DID möglicherweise nicht. Bit 1 gibt die Unterstützung von NAD an. HCE-Geräte dürfen NAD nicht unterstützen und müssen Bit 1 auf Null setzen.
  • Bisherige Bytes: HCE-Geräte können bis zu 15 bisherige Bytes zurückgeben. NFC-Lesegeräte, die mit HCE-Diensten interagieren möchten, dürfen keine Annahmen über den Inhalt der bisherigen Bytes oder deren Vorhandensein treffen.

Viele HCE-Geräte entsprechen wahrscheinlich den Protokollanforderungen, die die in EMVCo zusammengeschlossenen Zahlungsnetzwerke in ihrer Spezifikation „Contactless Communication Protocol“ festgelegt haben. Insbesondere

  • FSCI in T0 muss zwischen 2 und 8 Stunden liegen.
  • T(A)1 muss auf 0x80 gesetzt sein, was bedeutet, dass nur die Bitrate von 106 kbit/s unterstützt wird und asymmetrische Bitraten zwischen Lesegerät und Emulator nicht unterstützt werden.
  • FWI in T(B)1 muss <= 7 Stunden sein.

APDU-Datenaustausch

Wie bereits erwähnt, unterstützen HCE-Implementierungen nur einen einzigen logischen Kanal. Der Versuch, Anwendungen auf verschiedenen logischen Kanälen auszuwählen, funktioniert auf einem HCE-Gerät nicht.