Подсистема Gatekeeper выполняет аутентификацию по графическому ключу или паролю в доверенной среде выполнения (TEE). Gatekeeper регистрирует и проверяет пароли, используя секретный ключ на аппаратной основе. Кроме того, Gatekeeper ограничивает количество последовательных неудачных попыток подтверждения и должен отказывать в обслуживании запросов на обслуживание на основе заданного времени ожидания и заданного количества последовательных неудачных попыток.
Когда пользователи подтверждают свои пароли, Gatekeeper выдает токен аутентификации, подписанный ключом HMAC для каждой загрузки, который доступен только для защищенных компонентов. Этот токен отправляется в аппаратное хранилище ключей. То есть токен аутентификации Gatekeeper уведомляет Keystore о том, что приложения могут использовать ключи, связанные с аутентификацией (например, ключи, созданные приложениями).
Архитектура
Gatekeeper состоит из трех основных компонентов:
gatekeeperd(демон Gatekeeper) – сервис C++ Binder в Android, который содержит независимую от платформы логику, реализующую интерфейс AIDLIGateKeeperServiceна основе базовой реализацииIGatekeeperот поставщика.- Сервис аппаратно-зависимого уровня (HAL) Gatekeeper – реализация интерфейса AIDL
IGatekeeper, зависящая от поставщика. Этот сервис HAL работает в Android, но основные функции Gatekeeper должны выполняться в защищенной среде, поэтому он обычно взаимодействует с Gatekeeper TA. - Доверенное приложение Gatekeeper (TA) – реализация от поставщика, которая выполняется в TEE и проверяет пароль или графический ключ.
LockSettingsService отправляет запрос (через Binder), который достигает демона gatekeeperd в ОС Android. Затем демон gatekeeperd отправляет запрос сервису HAL IGatekeeper, который, в свою очередь, обращается к доверенному приложению Gatekeeper в TEE.
Рисунок 1. Общая схема передачи данных для аутентификации с помощью GateKeeper.
Демон gatekeeperd предоставляет API платформы Android доступ к HAL и участвует в передаче отчетов об аутентификации устройств в Keystore.
Демон gatekeeperd запускается в собственном процессе и отделен от системного сервера.
Реализация HAL
Демон gatekeeperd использует HAL IGatekeeper для взаимодействия с базовым доверенным приложением Gatekeeper, чтобы выполнять аутентификацию по паролю. Реализация Gatekeeper TA должна поддерживать подпись (регистрацию) и проверку больших двоичных объектов. Все реализации должны соответствовать стандартному формату токена аутентификации (HardwareAuthToken), который генерируется при каждой успешной проверке пароля. Подробные сведения о содержании и семантике HardwareAuthToken приведены в определении HardwareAuthToken.aidl.
Реализации HAL IGatekeeper от поставщиков должны включать функции enroll и verify:
- Метод
enrollпринимает большой двоичный объект пароля, подписывает его и возвращает подпись в качестве дескриптора. Возвращаемый blob-объект (из вызоваenroll) должен иметь структуру, показанную вsystem/gatekeeper/include/gatekeeper/password_handle.h. - Функция
verifyдолжна сравнивать подпись, созданную предоставленным паролем, и обеспечивать ее соответствие зарегистрированному дескриптору пароля.
Ключ, используемый для регистрации и проверки, не должен меняться и должен быть доступен для повторного получения при каждой загрузке устройства.
Trusty и другие реализации
Операционная система Trusty – это разработанная Google доверенная ОС с открытым исходным кодом для сред TEE, которая содержит одобренную реализацию Gatekeeper. Однако Gatekeeper можно реализовать в любой ОС TEE, если у TEE есть доступ к постоянному ключу с аппаратной защитой и защищенным монотонным часам, которые работают в режиме ожидания.
Trusty использует внутреннюю систему IPC для передачи общего секрета напрямую между KeyMint (ранее Keymaster) и реализацией Gatekeeper в Trusty (Trusty Gatekeeper). Этот общий секретный ключ используется для подписи токенов аутентификации, отправляемых в Keystore для подтверждения проверки пароля. Trusty Gatekeeper запрашивает ключ у KeyMint при каждом использовании и не сохраняет и не кеширует значение. Реализации могут передавать этот секрет любым способом, не ставящим под угрозу безопасность.
Ключ HMAC, используемый для регистрации и проверки паролей, создается и хранится только в Gatekeeper.
Android предоставляет общую реализацию Gatekeeper на C++, для которой требуется только добавление процедур, специфичных для устройства. Реализация Trusty основана на этом. Чтобы реализовать Gatekeeper в TEE с кодом для конкретного устройства, ознакомьтесь с функциями и комментариями в system/gatekeeper/include/gatekeeper/gatekeeper.h. Основные требования к реализации:
- Соответствие HAL
IGatekeeper. - Возвращаемые токены аутентификации должны быть отформатированы в соответствии со спецификацией
HardwareAuthToken(описана вHardwareAuthToken.aidl). - Gatekeeper в TEE должен иметь возможность передавать ключ HMAC в KeyMint одним из следующих способов:
- Соглашение об общем секрете. Gatekeeper может участвовать в согласовании ключа HMAC при каждой загрузке, реализуя HAL
ISharedSecret. Для этого у Gatekeeper и KeyMint должен быть доступ к общему предварительному ключу. - Прямой доступ. Gatekeeper может получить ключ HMAC из KeyMint, используя внутренний механизм межпроцессного взаимодействия TEE, по запросу или при первом использовании (с последующим кешированием).
- Соглашение об общем секрете. Gatekeeper может участвовать в согласовании ключа HMAC при каждой загрузке, реализуя HAL
Идентификаторы безопасности пользователей (SID)
SID пользователя – это представление пользователя в TEE (без строгой связи с идентификатором пользователя Android). SID генерируется с помощью криптографического генератора псевдослучайных чисел (PRNG) каждый раз, когда пользователь регистрирует новый пароль, не указывая предыдущий. Это называется недоверенной повторной регистрацией и обычно происходит, только когда пользователь впервые задает пароль или графический ключ.
Доверенная повторная регистрация происходит, когда пользователь указывает действительный предыдущий пароль, например при смене пароля. В этом случае SID пользователя переносится в новый дескриптор пароля, сохраняя привязанные к нему ключи.
SID пользователя включается в аутентификацию HMAC вместе с паролем в дескрипторе пароля при регистрации пароля.
Идентификаторы SID пользователей включаются в HardwareAuthToken, возвращаемый функцией verify(), и связываются со всеми ключами Keystore, привязанными к аутентификации. Подробную информацию о формате HardwareAuthToken и Keystore можно найти в разделе Аутентификация.
Обратите внимание, что ненадежный вызов функции enroll() изменяет идентификатор безопасности пользователя, поэтому ключи, связанные с паролем, становятся бесполезными. Злоумышленники могут изменить пароль устройства, если они контролируют ОС Android, но при этом они уничтожают защищенные root-доступом конфиденциальные ключи.
Ограничение запросов
Gatekeeper должен быть способен безопасно ограничивать попытки подбора учетных данных пользователя. Как показано в GatekeeperVerifyResponse.aidl, HAL позволяет возвращать время ожидания в миллисекундах. Тайм-аут сообщает клиенту, что не следует снова вызывать Gatekeeper до истечения тайм-аута.
Контролер доступа не должен обрабатывать запросы на обслуживание, если есть ожидающее время ожидания.
Gatekeeper должен записать счетчик сбоев перед проверкой пароля пользователя. Если пароль подтвержден, счетчик неудачных попыток должен быть сброшен. Это предотвращает атаки, которые отключают ограничение скорости, отключая встроенную карту MMC (eMMC) после вызова verify. Функция enroll также проверяет пароль пользователя (если он указан) и должна быть ограничена таким же образом.
Если устройство поддерживает такую возможность, настоятельно рекомендуется записывать счетчик неудачных попыток в защищенное хранилище. Если устройство не поддерживает шифрование на уровне файлов или защищенное хранилище работает слишком медленно, можно использовать блок памяти с защитой от повторного воспроизведения (RPMB).