Portero

El subsistema Gatekeeper realiza la autenticación de patrón/contraseña del dispositivo en un entorno de ejecución confiable (TEE). Gatekeeper registra y verifica las contraseñas a través de un HMAC 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 en función de un tiempo de espera determinado y un número determinado de intentos fallidos consecutivos.

Cuando los usuarios verifican sus contraseñas, Gatekeeper utiliza el secreto compartido derivado de TEE para firmar una atestación de autenticación y enviarla al almacén de claves respaldado por hardware . Es decir, una atestación de Gatekeeper notifica a Keystore que las claves vinculadas a la autenticación (por ejemplo, claves que las aplicaciones han creado) pueden liberarse para que las utilicen las aplicaciones.

Arquitectura

Gatekeeper implica tres componentes principales:

  • gatekeeperd (demonio guardián). Un servicio de carpeta de C++ que contiene lógica independiente de la plataforma y corresponde a la interfaz Java GateKeeperService .
  • Capa de abstracción de hardware de gatekeeper (HAL) . La interfaz HAL en hardware/libhardware/include/hardware/gatekeeper.h y el módulo de implementación.
  • Portero (TEE) . La contraparte TEE de gatekeeperd . Una implementación de Gatekeeper basada en TEE.

Gatekeeper requiere la implementación de Gatekeeper HAL (específicamente las funciones en hardware/libhardware/include/hardware/gatekeeper.h ) y el componente Gatekeeper específico de TEE (basado en parte en el archivo de encabezado system/gatekeeper/include/gatekeeper/gatekeeper.h que incluye funciones virtuales puras para crear/acceder a claves y firmas informáticas).

LockSettingsService realiza una solicitud (a través de Binder) que llega al demonio gatekeeperd en el sistema operativo Android. El demonio gatekeeperd luego realiza una solicitud que llega a su contraparte (Gatekeeper) en el TEE:

Flujo de portero
Figura 1. Flujo de datos de alto nivel para la autenticación por parte de GateKeeper

El demonio gatekeeperd proporciona a las API del marco de Android acceso a HAL y participa en la generación de informes de autenticaciones de dispositivos a Keystore. El demonio gatekeeperd se ejecuta en su propio proceso y está separado del servidor del sistema.

Implementación HAL

El demonio gatekeeperd utiliza HAL para interactuar con la contraparte TEE del demonio gatekeeperd para la autenticación de contraseña. La implementación de HAL debe poder firmar (inscribir) y verificar blobs. Se espera que todas las implementaciones cumplan con el formato estándar para el token de autenticación (AuthToken) generado en cada verificación de contraseña exitosa. Para obtener detalles sobre el contenido y la semántica de AuthToken, consulte Formato de AuthToken .

Las implementaciones del archivo de encabezado hardware/libhardware/include/hardware/gatekeeper.h deben implementar las funciones enroll y verify :

  • La función enroll toma un blob de contraseña, lo firma y devuelve la firma como identificador. El blob devuelto (de una llamada para 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 utilizada para inscribirse y verificar nunca debe cambiar y debe poder volver a obtenerse en cada inicio del dispositivo.

Implementaciones confiables y otras

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

Trusty utiliza un sistema IPC interno para comunicar un secreto compartido directamente entre Keymaster y la implementación Trusty de Gatekeeper (el Trusty Gatekeeper ). Este secreto compartido se utiliza para firmar AuthTokens enviados a Keystore para proporcionar certificaciones de verificación de contraseña. Trusty Gatekeeper solicita la clave a Keymaster para cada uso y no conserva ni almacena en caché el valor. Las implementaciones son libres de compartir este secreto de cualquier forma que no comprometa la seguridad.

La clave HMAC utilizada para registrar y verificar contraseñas se deriva y se guarda únicamente en GateKeeper.

Android proporciona una implementación genérica de C++ de GateKeeper que solo requiere la adición de rutinas específicas del dispositivo para completarse. Para implementar un TEE Gatekeeper con código específico del dispositivo para su TEE, consulte las funciones y comentarios en system/gatekeeper/include/gatekeeper/gatekeeper.h . Para TEE GateKeeper, las responsabilidades principales de una implementación compatible incluyen:

  • Adhesión al Gatekeeper HAL.
  • Los AuthTokens devueltos deben tener el formato de acuerdo con la especificación AuthToken (descrita en Autenticación ).
  • El TEE Gatekeeper debe poder compartir una clave HMAC con Keymaster, ya sea solicitando la clave a través de un TEE IPC a pedido o manteniendo un caché válido del valor en todo momento.

Identificaciones seguras de usuario (SID)

Un SID de usuario es la representación TEE de un usuario (sin una conexión sólida con un ID de usuario de Android). El SID se genera con un generador de números pseudoaleatorios criptográficos (PRNG) cada vez que un usuario registra una nueva contraseña sin proporcionar una anterior. Esto se conoce como reinscripción no confiable y el marco de trabajo de Android no lo permite en circunstancias normales. Una reinscripción confiable ocurre cuando un usuario proporciona una contraseña anterior válida; en este caso, el SID de usuario se migra al nuevo identificador de contraseña, conservando las claves que estaban vinculadas a él.

El SID de usuario se asigna a HMAC junto con la contraseña en el identificador de contraseña cuando se registra la contraseña.

Los SID de usuario se escriben en el AuthToken devuelto por la función verify y se asocian a todas las claves del almacén de claves vinculadas a la autenticación (para obtener detalles sobre el formato de AuthToken y el almacén de claves, consulte Autenticación ). Como una llamada no confiable a la función enroll cambiará el SID del usuario, la llamada inutilizará las claves vinculadas a esa contraseña. Los atacantes pueden cambiar la contraseña del dispositivo si controlan el sistema operativo Android, pero en el proceso destruirán las claves confidenciales protegidas por raíz.

Solicitar limitación

GateKeeper debe poder limitar de forma segura los intentos de fuerza bruta en una credencial de usuario. Como se muestra en hardware/libhardware/include/hardware/gatekeeper.h , HAL permite devolver un tiempo de espera en milisegundos. El tiempo de espera informa al cliente que no vuelva 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 fallas antes de verificar la contraseña de un usuario. Si la verificación de la contraseña tiene éxito, se debe borrar el contador de errores. Esto evita ataques que impiden la limitación al desactivar el MMC integrado (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 acelerarse de la misma manera.

Si el dispositivo lo admite, se recomienda encarecidamente que el contador de fallas se escriba en un almacenamiento seguro. Si el dispositivo no admite el cifrado basado en archivos, o si el almacenamiento seguro es demasiado lento, las implementaciones pueden usar el Bloque de memoria protegida de reproducción (RPMB) directamente.