Android NFC: как маршрутизировать APDU для одного определенного AID для защиты элемента UICC (маршрутизация вне хоста)
У меня есть SIM-карта с апплетом (карточкой) на нем. Если я могу установить для защищенного элемента по умолчанию на устройстве Android значение UICC, я могу отправлять команды через бесконтактный интерфейс в UICC.
Мой считыватель NFC отправляет APDU с "SELECT AID A0000001234567890" на контроллер NFC, который отправляет его моему апплету на защищенном элементе UICC (контроль доступа позаботился).
Теперь я хочу, чтобы это работало для устройств, где я не могу установить для защищенного элемента по умолчанию значение UICC.
Если я все правильно понял, так как для этого мне принципиально не нужно приложение Android, мне, тем не менее, придется использовать фиктивное приложение Android и объявить в своем манифесте так называемую "службу вне хоста".
Может ли кто-нибудь подсказать мне, что мне нужно сделать, чтобы маршрутизировать APDU, которые выбирают AID моего апплета, установленного на защищенном элементе, и последующие APDU к защищенному элементу UICC?
Вот моя первая попытка, но, возможно, у кого-то есть рабочий пример для меня или некоторые рекомендации / исправления.
AndroidManifest.xml:
<uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.nfc.hce" android:required="true" />
<service android:name=".OffHostApduService" 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"/>
<uses-feature android:name="android.hardware.nfc.hce" android:required="true" />
</service>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".Echo">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<uses-library
android:name="com.android.nfc_extras"
android:required="true" />
</activity>
</application>
apduservices.xml:
<offhost-apdu-service xmlns:android="http://schemas.android.com/apk/res/android" android:description="@string/servicedesc">
<aid-group android:description="@string/subscription" android:category="payment">
<aid-filter android:name="A0000001234567890"/>
</aid-group>
</offhost-apdu-service>
1 ответ
Ваш старт выглядит хорошо, и использование offhost-apdu-service должно нормально работать на устройствах, которые поддерживают обмен данными между эмуляцией карты и защищенным элементом. Обратите внимание, что некоторые устройства просто не поддерживают это, хотя.
Однако есть некоторые проблемы с вашими файлами XML:
Служба эмуляции карт в категории оплаты должна объявлять ресурс баннера отрисовываемым ресурсом. Баннер службы должен представлять собой графический файл (например, файл.png) с размерами 260 x 96 пикселей.
<offhost-apdu-service xmlns:android="http://schemas.android.com/apk/res/android" android:description="@string/servicedesc" android:apduServiceBanner="@drawable/servicebanner"> <aid-group android:category="payment" android:description="@string/servicedesc" > <aid-filter ... /> </aid-group> </offhost-apdu-service>
Службы должны быть объявлены в теге приложения в файле манифеста (обратите внимание, что я также изменяю имя службы, чтобы избежать конфликтов с именами класса framework):
<application ...> <activity ...> ... </activity> <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> </application>
Помимо объявления сервиса в вашем манифесте, вам также необходимо создать реализацию Java для сервиса. Что-то вроде:
public class MyOffHostApduService extends OffHostApduService { public IBinder onBind(Intent intent) { return null; } }
<uses-feature ...>
а также<uses-permission ...>
элементы должны быть прямыми дочерними элементами<manifest>
элемент (т.е. на том же уровне, что и<application ...>
элемент. Их нельзя использовать внутри других тегов (например, тег службы в вашем случае):<manifest ...> <uses-permission android:name="android.permission.NFC" /> <uses-feature android:name="android.hardware.nfc" android:required="true" /> <uses-feature android:name="android.hardware.nfc.hce" android:required="true" /> <application ...>
<uses-library ...>
элемент должен быть прямым потомком<application ...>
элемент. Тем не менее, вы, вероятно, не используете эту библиотеку в любом случае и можете полностью ее удалить.
Наконец, обратите внимание, что AID в вашем примере недопустим, поскольку он не выравнивается по полным байтам. Например, действительный AID будет A00000012345678900
, (Хотя я предполагаю, что это просто произошло во время маскировки вашего исходного AID для примера, верно?)