Многие устройства Android с поддержкой NFC уже поддерживают эмуляцию карт NFC. В большинстве случаев карта эмулируется отдельным чипом в устройстве, который называется защитным элементом. Многие SIM-карты, предоставляемые операторами беспроводной связи, также содержат защитный элемент.
В Android 4.4 и более поздних версиях предусмотрен дополнительный метод эмуляции карт, не требующий защитного элемента, – эмуляция карт на хосте. Это позволяет любому приложению для Android эмулировать карту и напрямую взаимодействовать со считывателем NFC. В этой статье рассказывается, как работает эмуляция карт на хосте (HCE) в Android и как разработать приложение, которое эмулирует NFC-карту с помощью этой технологии.
Эмуляция карты с защитным элементом
Если эмуляция карты NFC выполняется с помощью защитного элемента, то эмулируемая карта добавляется в защитный элемент на устройстве через приложение для Android. Когда пользователь подносит устройство к терминалу NFC, контроллер NFC на устройстве направляет все данные со считывателя непосредственно в защитный элемент. На рисунке 1 показано, как это работает.
Рисунок 1. Эмуляция карты NFC с защитным элементом.
Защитный элемент сам обменивается данными с NFC-терминалом, и в транзакции не участвует ни одно приложение для Android. После завершения транзакции приложение для Android может напрямую запросить у защитного элемента статус транзакции и уведомить пользователя.
Эмуляция карт на основе хоста
При эмуляции карты NFC на хосте данные направляются непосредственно на центральный процессор хоста, а не на защитный элемент. На рисунке 2 показано, как работает эмуляция карт на хосте.
Рисунок 2. Эмуляция карты NFC без защитного элемента.
Поддерживаемые карты и протоколы NFC
Рисунок 3. Стек протоколов HCE в Android.
Стандарты NFC поддерживают множество разных протоколов, и вы можете эмулировать разные типы карт.
В Android 4.4 и более поздних версиях поддерживается несколько протоколов, которые широко используются в настоящее время. Многие бесконтактные карты, например платежные, уже работают на основе этих протоколов. Эти протоколы также поддерживаются многими NFC-считывателями, представленными на рынке, в том числе устройствами Android с NFC, которые сами могут работать как считыватели (см. класс IsoDep). Это позволяет создавать и развертывать комплексные решения NFC на основе HCE, используя только устройства Android.
В частности, Android 4.4 и более поздние версии поддерживают эмуляцию карт на основе спецификации NFC-Forum ISO-DEP (на основе ISO/IEC 14443-4) и обрабатывают блоки данных протокола приложений (APDU), как определено в спецификации ISO/IEC 7816-4. Android требует эмуляции ISO-DEP только поверх технологии Nfc-A (ISO/IEC 14443-3 Type A). Поддержка технологии Nfc-B (ISO/IEC 14443-4 Type B) необязательна. На рисунке 3 показано, как эти спецификации накладываются друг на друга.
Сервисы HCE
Архитектура HCE в Android основана на компонентах Service (также известных как сервисы HCE). Одно из ключевых преимуществ сервиса заключается в том, что он может работать в фоновом режиме без пользовательского интерфейса. Это удобно для многих приложений, использующих эмуляцию хост-карты, например для карт постоянного клиента или транспортных карт, которые пользователь должен иметь возможность использовать без запуска приложения. Вместо этого прикладывание устройства к NFC-считывателю запускает нужный сервис, если он ещё не запущен, и выполняет транзакцию в фоновом режиме. Конечно, при необходимости вы можете запускать дополнительные элементы интерфейса (например, уведомления) из своего сервиса.
Выбор сервиса
Когда пользователь подносит устройство к NFC-считывателю, система Android должна знать, с каким сервисом HCE хочет связаться NFC-считыватель. В спецификации ISO/IEC 7816-4 описан способ выбора приложений на основе идентификатора приложения (AID). Идентификатор приложения состоит из 16 байт. Если вы эмулируете карты для существующей инфраструктуры NFC-считывателей, то идентификаторы приложений, которые ищут эти считыватели, обычно хорошо известны и общедоступны (например, идентификаторы приложений платежных систем, таких как Visa и MasterCard).
Если вы хотите развернуть новую инфраструктуру считывателей для своего приложения, вам нужно зарегистрировать собственные идентификаторы приложений. Процедура регистрации AID описана в спецификации ISO/IEC 7816-5. Если вы развертываете приложение HCE для Android, рекомендуем зарегистрировать AID в соответствии со стандартом 7816-5, чтобы избежать конфликтов с другими приложениями.
Группы AID
В некоторых случаях для реализации определенного приложения сервису HCE может потребоваться зарегистрировать несколько AID и быть установленным в качестве обработчика по умолчанию для всех AID. Нельзя перенести в другой сервис только некоторые идентификаторы AID из группы.
Список идентификаторов приложений, которые хранятся вместе, называется группой идентификаторов приложений. Для всех идентификаторов AID в группе Android гарантирует одно из следующих условий:
- Все идентификаторы приложений в группе направляются в этот сервис HCE.
- Ни один идентификатор приложения из группы не направляется в этот сервис HCE (например, потому что пользователь предпочел другой сервис, который также запросил один или несколько идентификаторов приложений из вашей группы).
Иными словами, промежуточного состояния, когда некоторые идентификаторы приложений в группе могут быть направлены в один сервис HCE, а некоторые – в другой, не существует.
Группы и категории AID
Каждую группу AID можно связать с категорией. Это позволяет Android группировать сервисы HCE по категориям, а пользователю – задавать настройки по умолчанию на уровне категории, а не AID. Не упоминайте идентификаторы приложений в пользовательском интерфейсе, поскольку они не имеют значения для обычного пользователя.
В Android 4.4 и более поздних версиях поддерживаются две категории:
CATEGORY_PAYMENT(включая стандартные платежные приложения)CATEGORY_OTHER(для всех остальных приложений HCE)
Приложения, регистрирующие идентификаторы AID в категории CATEGORY_PAYMENT, могут обрабатывать транзакции, только если:
- Пользователь устанавливает приложение в качестве платежного приложения по умолчанию (держатель роли Кошелька на устройствах с Android 15 и более поздних версий).
- Приложение работает в активном режиме и вызывает
setPreferredService.
Реализация сервиса HCE
Чтобы эмулировать NFC-карту с помощью HCE, необходимо создать компонент Service, который обрабатывает NFC-транзакции.
Проверьте поддержку HCE
Чтобы проверить, поддерживает ли устройство технологию HCE, используйте функцию FEATURE_NFC_HOST_CARD_EMULATION. Чтобы указать, что приложение использует функцию HCE и требуется ли она для его работы, добавьте в манифест тег <uses-feature>.
Реализация сервиса
В Android 4.4 и более поздних версиях есть удобный класс Service, который можно использовать в качестве основы для реализации сервиса HCE: класс HostApduService.
Сначала расширьте класс HostApduService, как показано в примере кода ниже.
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 объявляет два абстрактных метода, которые необходимо переопределить и реализовать. Один из них, processCommandApdu(), вызывается каждый раз, когда NFC-считыватель отправляет блок данных протокола приложения (APDU) в ваш сервис. Блоки APDU определены в спецификации ISO/IEC 7816-4. APDU – это пакеты уровня приложения, которыми обмениваются NFC-считыватель и ваш сервис HCE. Этот протокол уровня приложения является полудуплексным: NFC-считыватель отправляет вам командный блок APDU и ожидает, пока вы отправите ответный блок APDU.
Как упоминалось ранее, Android использует AID, чтобы определить, с каким сервисом HCE хочет связаться считыватель. Обычно первый блок APDU, который NFC-считыватель отправляет на устройство, – это блок SELECT AID, содержащий идентификатор AID, с которым считыватель хочет связаться. Android извлекает этот AID из APDU, сопоставляет его с сервисом HCE, а затем пересылает APDU этому сервису.
Чтобы отправить ответный APDU, верните байты ответного APDU из processCommandApdu(). Обратите внимание, что этот метод вызывается в основном потоке приложения, который не должен блокироваться. Если вы не можете сразу вычислить и вернуть ответный APDU, верните null. Затем вы можете выполнить необходимые действия в другом потоке и использовать метод sendResponseApdu(), определенный в классе HostApduService, чтобы отправить ответ.
Android продолжает пересылать новые APDU от считывателя в ваш сервис, пока не произойдет одно из следующих событий:
- NFC-считыватель отправляет ещё один блок
SELECT AIDAPDU, который ОС сопоставляет с другим сервисом. - Связь между устройством и считывателем NFC прервана.
В обоих случаях вызывается реализация onDeactivated() вашего класса с аргументом, указывающим, какое из двух событий произошло.
Если вы работаете с существующей инфраструктурой считывателей, вам необходимо реализовать в сервисе HCE существующий протокол уровня приложения, который ожидают считыватели.
Если вы развертываете новую инфраструктуру считывателей, которой управляете, то можете определить собственный протокол и последовательность APDU. Постарайтесь ограничить количество APDU и размер передаваемых данных, чтобы пользователям не приходилось долго держать устройство у NFC-считывателя. Разумный верхний предел – около 1 КБ данных, которые обычно можно передать за 300 мс.
Декларация манифеста сервиса и регистрация AID
Вам нужно объявить службу в манифесте, как обычно, но также добавить в объявление некоторые дополнительные элементы:
Чтобы сообщить платформе, что это сервис HCE, реализующий интерфейс
HostApduService, добавьте фильтр интентов для действияSERVICE_INTERFACEв объявление сервиса.Чтобы указать, какие группы AID запрашиваются этим сервисом, добавьте тег
SERVICE_META_DATA<meta-data>в объявление сервиса, указывающее на ресурс XML с дополнительной информацией о сервисе HCE.Задайте для атрибута
android:exportedзначениеtrueи запросите разрешениеandroid.permission.BIND_NFC_SERVICEв декларации сервиса. Первое гарантирует, что сервис может быть связан с внешними приложениями. В этом случае только внешние приложения с разрешениемandroid.permission.BIND_NFC_SERVICEсмогут подключаться к вашему сервису. Посколькуandroid.permission.BIND_NFC_SERVICE– это системное разрешение, оно гарантирует, что только ОС Android может подключаться к вашему сервису.
Ниже приведен пример объявления манифеста 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>
Этот тег метаданных указывает на файл apduservice.xml. Ниже приведен пример такого файла с объявлением одной группы AID, содержащей два собственных AID:
<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>
Тег <host-apdu-service> должен содержать атрибут <android:description> с удобным описанием сервиса, которое можно показывать в интерфейсе приложения. Вы можете использовать атрибут requireDeviceUnlock, чтобы указать, что устройство должно быть разблокировано, прежде чем вы вызовете этот сервис для обработки APDU.
Тег <host-apdu-service> должен содержать один или несколько тегов <aid-group>. Каждый тег <aid-group> должен выполнять следующие действия:
- Содержать атрибут
android:descriptionс удобным описанием группы AID, которое можно показывать в интерфейсе. - Иметь атрибут
android:category, указывающий на категорию, к которой относится группа AID, например строковые константы, определенныеCATEGORY_PAYMENTилиCATEGORY_OTHER. - Содержать один или несколько тегов
<aid-filter>, каждый из которых содержит один идентификатор AID. Укажите идентификатор приложения в шестнадцатеричном формате. Он должен содержать четное количество символов.
Чтобы зарегистрироваться в качестве сервиса HCE, приложению также требуется разрешение NFC.
Разрешение конфликтов AID
На одном устройстве может быть установлено несколько компонентов HostApduService, и один и тот же идентификатор AID может быть зарегистрирован несколькими сервисами. Android определяет, какой сервис вызвать, следующим образом:
- Если AID зарегистрирован в приложении кошелька, выбранном по умолчанию, то вызывается это приложение.
- Если приложение кошелька по умолчанию не зарегистрировало AID, вызывается сервис, который зарегистрировал AID.
- Если идентификатор AID зарегистрирован в нескольких сервисах, Android предлагает пользователю выбрать нужный.
Предпочтения в отношении активных служб
Активные приложения могут вызывать setPreferredService, чтобы указать, какой сервис эмуляции карт должен быть предпочтительным, пока активно определенное действие. Приоритет активного приложения переопределяет разрешение конфликтов AID. Это рекомендуется делать, если приложение предполагает, что пользователь может использовать эмуляцию карты NFC.
Android 13 и более поздних версий
Чтобы баннер лучше вписывался в список выбора способа оплаты по умолчанию в настройках, мы изменили требование к нему. Теперь это должен быть квадратный значок. В идеале он должен быть идентичен дизайну значка программы запуска приложений. Это изменение делает дизайн более единообразным и аккуратным.
Android 12 и более ранние версии
Задайте размер баннера сервиса 260 x 96 dp, а затем укажите его в XML-файле метаданных, добавив атрибут android:apduServiceBanner в тег <host-apdu-service>, который указывает на прорисовываемый ресурс. Пример:
<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>
Приложения-кошельки
В Android 15 и более поздних версиях есть роль приложения-кошелька по умолчанию, которую пользователь может выбрать в разделе Настройки > Приложения > Приложения по умолчанию. Это определяет приложение бумажника по умолчанию, которое будет запускаться при взаимодействии с кассовым терминалом. Сервисы HCE, в которых объявлена группа AID с категорией оплаты, считаются приложениями-кошельками.
Как проверить, является ли ваше приложение кошельком по умолчанию
Приложения могут проверять, являются ли они кошельком по умолчанию, передавая RoleManager.ROLE_WALLET в RoleManager.isRoleHeld().
Если ваше приложение не является кошельком по умолчанию, вы можете запросить эту роль, передав RoleManager.ROLE_WALLET в RoleManager.createRequestRoleIntent().
Объекты, необходимые для приложений-кошельков
Для обеспечения более привлекательного пользовательского интерфейса приложения HCE-кошельков должны предоставлять баннер сервиса.
Режим наблюдения
В Android 15 появился режим наблюдения. В режиме наблюдения устройство может отслеживать циклы опроса NFC и отправлять уведомления о них соответствующим компонентам HostApduService, чтобы они могли подготовиться к взаимодействию с определенным терминалом NFC. HostApduService может перевести устройство в режим наблюдения, передав true в setObserveModeEnabled().
Это указывает стеку NFC не разрешать NFC-транзакции, а пассивно наблюдать за циклами опроса.
Фильтры цикла опроса
Зарегистрировать фильтры цикла опроса для HostApduService можно одним из следующих способов:
registerPollingLoopFilterForService()– для фильтров, которые должны точно соответствовать кадру опроса.registerPollingLoopPatternFilterForService()для фильтров, которые сопоставляют регулярное выражение с кадрами опроса.
Когда фильтр цикла опроса совпадает с нестандартными кадрами опроса, стек NFC направляет эти кадры опроса в соответствующий сервис HostApduService, вызывая его метод processPollingFrames(). Это позволяет сервису предпринять все необходимые шаги, чтобы убедиться, что пользователь готов к транзакции и намерен ее совершить, например выполнить аутентификацию пользователя. Если NFC-считыватель использует в цикле опроса только стандартные фреймы, стек NFC направляет их в предпочитаемую активную службу, если она находится на переднем плане, или в кошелек по умолчанию.
Уведомления о кадрах опроса также включают в себя измерение напряженности поля, зависящее от поставщика, которое можно получить, вызвав getVendorSpecificGain().
Поставщики могут предоставлять измерения по собственной шкале, если они укладываются в один байт.
Как реагировать на циклы опроса и выйти из режима наблюдения
Когда сервис будет готов к транзакциям, он может выйти из режима наблюдения, передав false в setObserveModeEnabled(). После этого стек NFC разрешит выполнение транзакций.
Компоненты HostApduService могут указывать, что режим наблюдения должен быть включен, когда они являются предпочтительным платежным сервисом. Для этого нужно задать для shouldDefaultToObserveMode значение true в манифесте или вызвать CardEmulation.setShouldDefaultToObserveModeForService().
Компоненты HostApduService и OffHostApduService также могут указывать, что фильтры цикла опроса, соответствующие полученным кадрам цикла опроса, должны автоматически отключать режим наблюдения и разрешать транзакции. Для этого нужно задать для autoTransact значение true в объявлении PollingLoopFilter в манифесте.
Предпочтения в отношении активных служб
Активные приложения могут вызывать метод setPreferredService, чтобы указать, какой сервис эмуляции карт должен быть предпочтительным, пока определенное действие выполняется на переднем плане. Эта настройка активного приложения переопределяет состояние режима наблюдения устройства, соответствующее значению shouldDefaultToObserveMode для определенного сервиса, которое можно задать одним из следующих способов:
- Задайте состояние
shouldDefaultToObserveModeв манифесте для этого сервиса. - Вызов
CardEmulation.setShouldDefaultToObserveModeForService()с соответствующим сервисом и состоянием.
Поведение при выключенном и заблокированном экране
Поведение сервисов HCE зависит от версии Android, установленной на устройстве.
Android 15 и более поздних версий
Если приложение кошелька по умолчанию включает режим наблюдения на устройстве, которое его поддерживает, то это приложение переопределяет поведение разблокировки и выключения экрана, поскольку оно контролирует, когда транзакция может быть продолжена. Если режим наблюдения не обнаружил идентифицируемый шаблон цикла опроса, некоторые приложения кошельков могут потребовать разблокировать устройство перед выполнением транзакции.
Разработчикам рекомендуется настроить свои считывающие устройства так, чтобы они передавали идентифицируемые шаблоны цикла опроса, и зарегистрировать обработку этих шаблонов в приложении.
Android 12 и более поздних версий
В приложениях для Android 12 (уровень API 31) и более поздних версий можно включить оплату через NFC без включения экрана устройства, задав для requireDeviceScreenOn значение false.
Android 10 и более поздних версий
Устройства с Android 10 (уровень API 29) или более поздней версии поддерживают защиту NFC. Если защита NFC включена, то все эмуляторы карт (размещаемые и внешние приложения) недоступны, когда экран устройства выключен. Если защита NFC отключена, то внешние приложения доступны, когда экран устройства выключен. Проверить, поддерживается ли защита NFC, можно с помощью метода isSecureNfcSupported().
На устройствах с Android 10 и более поздними версиями ОС параметр android:requireDeviceUnlock со значением true работает так же, как и на устройствах с Android 9 и более ранними версиями ОС, но только если защита NFC отключена. Это означает, что если защита NFC включена, то сервисы HCE не могут работать на заблокированном экране независимо от значения параметра android:requireDeviceUnlock.
Android 9 и более ранних версий
На устройствах с Android 9 (уровень API 28) и более ранними версиями контроллер NFC и процессор приложений полностью отключаются, когда экран устройства выключен. Поэтому сервисы HCE не работают, когда экран выключен.
Кроме того, на устройствах с Android 9 и более ранними версиями сервисы HCE могут работать на заблокированном экране.
Однако это определяется атрибутом android:requireDeviceUnlock в теге <host-apdu-service> вашего сервиса HCE. По умолчанию разблокировка устройства не требуется, и ваш сервис вызывается, даже если устройство заблокировано.
Если вы зададите для атрибута android:requireDeviceUnlock значение true для своей службы HCE, Android будет предлагать пользователю разблокировать устройство в следующих случаях:
- Пользователь нажимает на NFC-считыватель.
- NFC-считыватель выбирает идентификатор приложения, который разрешается в ваш сервис.
После разблокировки Android показывает диалоговое окно с предложением снова приложить устройство, чтобы завершить транзакцию. Это необходимо, поскольку пользователь мог убрать устройство от NFC-считывателя, чтобы разблокировать его.
Сосуществование с картами с защитным элементом
Этот раздел предназначен для разработчиков, которые развернули приложение, использующее защитный элемент для эмуляции карты. Реализация HCE в Android позволяет использовать эту технологию параллельно с другими методами эмуляции карт, включая защитные элементы.
Это сосуществование основано на принципе, называемом маршрутизацией AID. Контроллер NFC хранит таблицу маршрутизации, которая состоит из (конечного) списка правил маршрутизации. Каждое правило маршрутизации содержит идентификатор приложения и пункт назначения. Это может быть как хост-ЦП, на котором работают приложения Android, так и подключенный защитный элемент.
Когда считыватель NFC отправляет APDU с SELECT AID, контроллер NFC анализирует его и проверяет, совпадают ли AID с какими-либо AID в его таблице маршрутизации. Если совпадение есть, этот и все последующие APDU отправляются в пункт назначения, связанный с AID, пока не будет получен другой APDU SELECT AID или не прервется NFC-соединение.
Эта архитектура показана на рисунке 4.
Рисунок 4. Android с защитным элементом и эмуляцией хост-карты.
Контроллер NFC обычно также содержит маршрут по умолчанию для APDU. Если идентификатор AID не найден в таблице маршрутизации, используется маршрут по умолчанию. Хотя эта настройка может отличаться на разных устройствах, на устройствах Android необходимо убедиться, что идентификаторы AID, регистрируемые вашим приложением, правильно маршрутизируются на хост.
Приложениям для Android, которые реализуют сервис HCE или используют защитный элемент, не нужно настраивать таблицу маршрутизации. Это делается автоматически. Android нужно лишь знать, какие идентификаторы приложений могут обрабатываться сервисами HCE, а какие – защитным элементом. Таблица маршрутизации настраивается автоматически в зависимости от того, какие сервисы установлены и какие из них пользователь выбрал в качестве предпочтительных.
В следующем разделе объясняется, как объявить AID для приложений, которые используют защитный элемент для эмуляции карты.
Регистрация идентификатора приложения в защитном элементе
Приложения, использующие защитный элемент для эмуляции карт, могут объявить в манифесте сервис, работающий вне хоста. Декларация такого сервиса практически идентична декларации сервиса HCE. Исключения:
- Для действия, используемого в фильтре интентов, должно быть задано значение
SERVICE_INTERFACE. - Атрибут name должен иметь значение
SERVICE_META_DATA. В XML-файле метаданных должен использоваться корневой тег
<offhost-apdu-service>.<service android:name=".MyOffHostApduService" android:secureElementName="eSE" 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>
Ниже приведен пример соответствующего файла apduservice.xml, в котором зарегистрированы два идентификатора AID:
<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>
Атрибут android:requireDeviceUnlock не применяется к сервисам, работающим без хоста, поскольку ЦП хоста не участвует в транзакции и не может запретить защитному элементу выполнять транзакции, когда устройство заблокировано.
Атрибут android:apduServiceBanner обязателен для сервисов, которые не размещены на хосте и являются платежными приложениями, а также для приложений, которые можно выбрать в качестве платежных по умолчанию.
Вызов сервиса вне хоста
Android никогда не запускает и не привязывает сервис, объявленный как off-host, поскольку фактические транзакции выполняются защитным элементом, а не сервисом Android. Декларация сервиса позволяет приложениям регистрировать идентификаторы приложений, присутствующие в защитном элементе.
HCE и безопасность
Архитектура HCE обеспечивает один из основных элементов безопасности: поскольку ваш сервис защищен системным разрешением BIND_NFC_SERVICE, только ОС может подключаться к нему и взаимодействовать с ним.
Это гарантирует, что любой блок APDU, который вы получаете, действительно был получен ОС от контроллера NFC, а любой блок APDU, который вы отправляете обратно, поступает только в ОС, которая, в свою очередь, напрямую пересылает блоки APDU контроллеру NFC.
Последний вопрос, который нам осталось рассмотреть, – откуда приложение берет данные, которые отправляет на NFC-считыватель. Это сделано намеренно. Для HCE не имеет значения, откуда поступают данные. Главное – обеспечить их безопасную передачу на контроллер NFC и далее на считывающее устройство.
Для безопасного хранения и получения данных, которые вы хотите отправить из своего сервиса HCE, вы можете, например, использовать песочницу приложений для Android, которая изолирует данные вашего приложения от других приложений. Подробнее о безопасности Android…
Параметры и сведения о протоколе
Этот раздел предназначен для разработчиков, которые хотят узнать, какие параметры протокола используются устройствами с HCE на этапах предотвращения коллизий и активации протоколов NFC. Это позволяет создать инфраструктуру считывателей, совместимую с устройствами Android, на которых используется эмуляция хост-карты.
Предотвращение конфликтов и активация протокола Nfc-A (ISO/IEC 14443 тип A)
В рамках активации протокола Nfc-A происходит обмен несколькими фреймами.
На первом этапе устройство HCE предоставляет свой UID. Предполагается, что у устройств HCE случайный UID. Это означает, что при каждом касании считывателю передается случайно сгенерированный UID. Поэтому считыватели NFC не должны использовать UID устройств HCE для аутентификации или идентификации.
Затем NFC-считыватель может выбрать устройство с HCE, отправив команду SEL_REQ. В ответе SEL_RES устройства HCE должен быть установлен как минимум шестой бит
(0x20), указывающий на поддержку ISO-DEP. Также могут быть установлены и другие биты
SEL_RES, например указывающие на поддержку протокола NFC-DEP
(p2p). Поскольку могут быть установлены и другие биты, считыватели, взаимодействующие с устройствами HCE, должны проверять только шестой бит, а не сравнивать весь байт SEL_RES со значением 0x20.
Активация ISO-DEP
После активации протокола Nfc-A NFC-считыватель инициирует активацию протокола ISO-DEP. Оно отправляет команду RATS (Request for Answer To Select). Контроллер NFC генерирует ответ RATS, ATS; ATS не настраивается сервисами HCE. Однако реализации HCE должны соответствовать требованиям NFC Forum к ответу ATS, поэтому считыватели NFC могут рассчитывать на то, что эти параметры будут заданы в соответствии с требованиями NFC Forum для любого устройства HCE.
Ниже приведена подробная информация об отдельных байтах ответа ATS, предоставляемого контроллером NFC на устройстве HCE.
- TL – длина ответа ATS. Длина не должна превышать 20 байт.
- T0: биты 5, 6 и 7 должны быть установлены на всех устройствах HCE, что указывает на включение TA(1), TB(1) и TC(1) в ответ ATS. Биты с 1 по 4 указывают на FSCI, кодируя максимальный размер кадра. На устройствах с HCE значение FSCI должно быть от 0h до 8h.
- T(A)1: определяет битрейт между считывателем и эмулятором, а также то, могут ли они быть асимметричными. Для устройств с HCE нет требований к скорости передачи данных или гарантий.
- T(B)1: биты 1–4 указывают на целое число, определяющее время защитного интервала кадра запуска (SFGI). На устройствах с HCE значение SFGI должно быть не больше 8 часов. Биты с 5 по 8 указывают на целое число времени ожидания кадра (FWI) и кодируют время ожидания кадра (FWT). На устройствах с HCE значение FWI должно быть меньше или равно 8h.
- T(C)1: бит 5 указывает на поддержку расширенных функций протокола. Устройства с HCE могут поддерживать или не поддерживать расширенные функции протокола. Бит 2 указывает на поддержку DID. Устройства с HCE могут поддерживать или не поддерживать DID. Бит 1 указывает на поддержку NAD. Устройства с поддержкой HCE не должны поддерживать NAD и должны устанавливать бит 1 в значение 0.
- Исторические байты. Устройства с HCE могут возвращать до 15 исторических байтов. NFC-считыватели, взаимодействующие с сервисами HCE, не должны делать предположений о содержимом или наличии исторических байтов.
Обратите внимание, что многие устройства с HCE, скорее всего, соответствуют требованиям протокола, которые платежные сети, объединенные в EMVCo, указали в своей спецификации "Протокол бесконтактной связи". В частности, нужно проверять следующее:
- FSCI в T0 должно быть от 2 до 8 часов.
- Для T(A)1 должно быть задано значение 0x80, указывающее, что поддерживается только скорость передачи данных 106 кбит/с, а асимметричные скорости передачи данных между считывателем и эмулятором не поддерживаются.
- FWI в T(B)1 должно быть <= 7 ч.
Обмен данными APDU
Как отмечалось ранее, реализации HCE поддерживают только один логический канал. Попытка выбрать приложения на разных логических каналах не работает на устройстве с HCE.