Gatekeeper

El subsistema Gatekeeper realiza la autenticación de patrones o contraseñas del dispositivo en un entorno de ejecución confiable (TEE). Gatekeeper registra y verifica contraseñas con una clave secreta respaldada por hardware. Además, Gatekeeper limita los intentos de verificación fallidos consecutivos y debe rechazar las solicitudes de servicio según un tiempo de espera y una cantidad determinados de intentos fallidos consecutivos.

Cuando los usuarios verifican sus contraseñas, Gatekeeper emite un token de autenticación firmado con una clave HMAC por arranque que solo está disponible para los componentes seguros, y este token se envía al almacén de claves respaldado por hardware. Es decir, un token de autenticación de Gatekeeper notifica a Keystore que las apps pueden usar las claves vinculadas a la autenticación (por ejemplo, las claves que crearon las apps).

Arquitectura

Gatekeeper incluye tres componentes principales:

  • gatekeeperd (daemon de Gatekeeper): Es un servicio de Binder de C++ en Android que contiene lógica independiente de la plataforma que implementa la interfaz de AIDL IGateKeeperService, basada en una implementación subyacente específica del proveedor de IGatekeeper.
  • Servicio de la capa de abstracción de hardware (HAL) de Gatekeeper: Es una implementación específica del proveedor de la interfaz AIDL IGatekeeper. Este servicio de HAL se ejecuta en Android, pero la funcionalidad principal de Gatekeeper debe ejecutarse en un entorno seguro, por lo que suele comunicarse con el TA de Gatekeeper.
  • Aplicación de confianza (TA) de Gatekeeper: Es una implementación específica del proveedor que se ejecuta en el TEE y realiza la verificación real de la contraseña o el patrón.

El LockSettingsService realiza una solicitud (a través de Binder) que llega al daemon gatekeeperd en el SO Android. Luego, el daemon gatekeeperd realiza una solicitud al servicio de HAL IGatekeeper, que, a su vez, llega a su TA de Gatekeeper correspondiente en el TEE:

Flujo de la persona responsable de filtrar conversaciones

Figura 1: Flujo de datos de alto nivel para la autenticación de GateKeeper.

El daemon gatekeeperd otorga a las APIs del framework de Android acceso al HAL y participa en el registro de autenticaciones del dispositivo en Keystore. El daemon gatekeeperd se ejecuta en su propio proceso y está separado del servidor del sistema.

Implementación del HAL

El daemon gatekeeperd usa el HAL IGatekeeper para interactuar con el TA subyacente de Gatekeeper para la autenticación con contraseña. La implementación de TA de Gatekeeper debe poder firmar (inscribir) y verificar BLOBs. Se espera que todas las implementaciones cumplan con el formato estándar del token de autenticación (HardwareAuthToken) que se genera en cada verificación de contraseña exitosa. Para obtener detalles sobre el contenido y la semántica de HardwareAuthToken, consulta la definición de HardwareAuthToken.aidl.

Las implementaciones del proveedor de la HAL de IGatekeeper deben implementar las funciones enroll y verify:

  • El método enroll toma un BLOB de contraseña, lo firma y devuelve la firma como un identificador. El BLOB que se devuelve (de una llamada a enroll) debe tener la estructura que se muestra en system/gatekeeper/include/gatekeeper/password_handle.h.
  • La función verify debe comparar la firma producida por la contraseña proporcionada y garantizar que coincida con el identificador de contraseña registrado.

La clave que se usa para inscribir y verificar nunca debe cambiar, y se debe poder volver a derivar en cada inicio del dispositivo.

Trusty y otras implementaciones

El sistema operativo Trusty es el SO de código abierto confiable de Google para entornos de TEE y contiene una implementación aprobada de Gatekeeper. Sin embargo, cualquier SO de TEE puede implementar Gatekeeper, siempre y cuando el TEE tenga acceso a una clave persistente respaldada por hardware y a un reloj seguro y monotónico que funcione en suspensión.

Trusty usa un sistema IPC interno para comunicar un secreto compartido directamente entre KeyMint (anteriormente Keymaster) y la implementación de Gatekeeper de Trusty (el Trusty Gatekeeper). Este secreto compartido se usa para firmar los AuthTokens que se envían a Keystore para proporcionar certificaciones de verificación de contraseñas. Trusty Gatekeeper solicita la clave a KeyMint para cada uso y no conserva ni almacena en caché el valor. Las implementaciones pueden compartir este secreto de cualquier manera que no comprometa la seguridad.

La clave HMAC que se usa para inscribir y verificar contraseñas se deriva y se mantiene únicamente en Gatekeeper.

Android proporciona una implementación genérica de Gatekeeper en C++ que solo requiere la adición de rutinas específicas del dispositivo para completarse. La implementación de Trusty se basa en esta. Para implementar un Gatekeeper de TEE con código específico del dispositivo para tu TEE, consulta las funciones y los comentarios en system/gatekeeper/include/gatekeeper/gatekeeper.h. Entre las responsabilidades principales de una implementación conforme, se incluyen las siguientes:

  • Cumplimiento del HAL de IGatekeeper
  • Los tokens de autenticación devueltos deben tener el formato de la especificación HardwareAuthToken (que se describe en Autenticación).
  • El Gatekeeper del TEE debe poder compartir una clave HMAC con KeyMint, ya sea solicitando la clave a través de un IPC del TEE a pedido o manteniendo una caché válida del valor en todo momento.

IDs seguros de usuario (SID)

Un SID de usuario es la representación del usuario en el TEE (sin una conexión sólida con un ID de usuario de Android). El SID se genera con un generador de números pseudoaleatorios (PRNG) criptográfico cada vez que un usuario inscribe una contraseña nueva sin proporcionar una anterior. Esto se conoce como un reenrollment no confiable y, por lo general, solo ocurre cuando un usuario establece una contraseña o un patrón por primera vez.

Un reenrollment confiable ocurre cuando un usuario proporciona una contraseña anterior válida, por ejemplo, cuando cambia la contraseña. En este caso, el SID del usuario se migra al nuevo identificador de contraseña, lo que conserva las claves que estaban vinculadas a él.

El SID del usuario se incluye en la autenticación HMAC junto con la contraseña en el identificador de contraseña cuando se inscribe la contraseña.

Los SID del usuario se incluyen en el HardwareAuthToken que devuelve la función verify() y se asocian a todas las claves de Keystore vinculadas a la autenticación (para obtener detalles sobre el formato HardwareAuthToken y Keystore, consulta Autenticación).

Ten en cuenta que, como una llamada no confiable a la función enroll() cambia el SID del usuario, la llamada hace que las claves vinculadas a esa contraseña sean inútiles. Los atacantes pueden cambiar la contraseña del dispositivo si controlan el SO Android, pero destruyen las claves sensibles protegidas por el administrador en el proceso.

Limitación de solicitudes

Gatekeeper debe poder limitar de forma segura los intentos de fuerza bruta en una credencial de usuario. Como se muestra en GatekeeperVerifyResponse.aidl, el HAL permite devolver un tiempo de espera en milisegundos. El tiempo de espera informa al cliente que no debe volver a llamar a Gatekeeper hasta que haya transcurrido el tiempo de espera. Gatekeeper no debe atender solicitudes si hay un tiempo de espera pendiente.

Gatekeeper debe escribir un contador de errores antes de verificar la contraseña de un usuario. Si la verificación de la contraseña se realiza correctamente, se debe borrar el contador de errores. Esto evita ataques que impiden la limitación de la velocidad, ya que inhabilita la MMC integrada (eMMC) después de emitir una llamada verify. La función enroll también verifica la contraseña del usuario (si se proporciona) y debe limitarse de la misma manera.

Si el dispositivo lo admite, se recomienda escribir el contador de fallas en el almacenamiento seguro. Si el dispositivo no admite la encriptación basada en archivos o si el almacenamiento seguro es demasiado lento, las implementaciones pueden usar directamente el bloque de memoria protegido contra repeticiones (RPMB).