El subsistema de Gatekeeper realiza la autenticación de patrones o contraseñas del dispositivo en un entorno de ejecución confiable (TEE). Gatekeeper inscribe 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 consecutivos fallidos y debe rechazar las solicitudes de servicio según un tiempo de espera determinado y una cantidad determinada de intentos fallidos consecutivos.
Cuando los usuarios verifican sus contraseñas, Gatekeeper usa el secreto compartido derivado de TEE para firmar una certificación de autenticación que se envía al almacén de claves respaldado por hardware. Es decir, una certificación de Gatekeeper notifica a Keystore que las claves vinculadas a la autenticación (por ejemplo, las claves que crearon las apps) se pueden liberar para que las usen las apps.
Arquitectura
El gatekeeper incluye tres componentes principales:
gatekeeperd
(daemon de Gatekeeper). Un servicio de Binder de C++ que contiene lógica independiente de la plataforma y corresponde a la interfaz de JavaGateKeeperService
.- Capa de abstracción de hardware (HAL) de Gatekeeper. La interfaz de HAL en
hardware/libhardware/include/hardware/gatekeeper.h
y el módulo de implementación - Gatekeeper (TEE): El equivalente de TEE de
gatekeeperd
. Una implementación de Gatekeeper basada en TEE.
Gatekeeper requiere la implementación del HAL de Gatekeeper (específicamente, las funciones de hardware/libhardware/include/hardware/gatekeeper.h
) y el componente de 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 o acceder a claves y calcular firmas).
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 que llega a su contraparte (Gatekeeper) en el TEE:

El daemon gatekeeperd
les otorga a las APIs del framework de Android acceso al HAL y participa en el informe de las autenticaciones del dispositivo al almacén de claves.
El daemon gatekeeperd
se ejecuta en su propio proceso y es independiente del servidor del sistema.
Implementación de HAL
El daemon de gatekeeperd
usa el HAL para interactuar con la contraparte de TEE del daemon de gatekeeperd
para la autenticación de contraseñas. La implementación de HAL debe poder firmar (inscribir) y verificar los BLOB. Se espera que todas las implementaciones cumplan con el formato estándar del token de autenticación (AuthToken) que se genera en cada verificación de contraseña correcta. Para obtener detalles sobre el contenido y la semántica de AuthToken, consulta 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 muestra la firma como un identificador. El blob que se muestra (de una llamada aenroll
) debe tener la estructura que se muestra ensystem/gatekeeper/include/gatekeeper/password_handle.h
. - La función
verify
debe comparar la firma que produce la contraseña proporcionada y asegurarse de que coincida con el identificador de contraseña inscrito.
La clave que se usa para la inscripción y la verificación 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 de confianza de Google para entornos de TEE y contiene una implementación aprobada de GateKeeper. Sin embargo, puedes usar cualquier SO TEE para implementar Gatekeeper, siempre y cuando el TEE tenga acceso a una clave respaldada por hardware y un reloj monótono y seguro que marque en suspensión.
Trusty usa un sistema IPC interno para comunicar un secreto compartido directamente entre Keymaster y la implementación de Gatekeeper de Trusty (el Gatekeeper de Trusty). Este secreto compartido se usa para firmar AuthTokens que se envían al almacén de claves para proporcionar certificaciones de verificación de contraseñas. El gatekeeper de confianza solicita la clave a Keymaster 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. 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
.
En el caso de TEE GateKeeper, las responsabilidades principales de una implementación conforme incluyen las siguientes:
- Cumplimiento del HAL de Gatekeeper
- Los AuthTokens que se devuelven deben tener el formato que se especifica en la especificación de AuthToken (que se describe en Autenticación).
- El gatekeeper de TEE debe poder compartir una clave HMAC con Keymaster, ya sea solicitando la clave a través de un IPC de 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 de 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 (PRNG) criptográfico cada vez que un usuario inscribe una contraseña nueva sin proporcionar una anterior. Esto se conoce como una nueva inscripción no confiable y el framework de Android no lo permite en circunstancias normales. Una reinscripción confiable se produce cuando un usuario proporciona una contraseña anterior válida. En este caso, el SID del usuario se migra al nuevo identificador de contraseña, conservando las claves que estaban vinculadas a él.
El SID del usuario se HMAC junto con la contraseña en el control de contraseña cuando esta se inscribe.
Los SID de usuario se escriben en el AuthToken que devuelve 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, consulta Autenticación). Como una llamada no confiable a la función enroll
cambiará el SID del usuario, la llamada hará 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 destruirán las claves sensibles protegidas por root en el proceso.
Limitación de solicitudes
GateKeeper debe poder limitar de forma segura los intentos de fuerza bruta en una credencial del usuario. Como se muestra en hardware/libhardware/include/hardware/gatekeeper.h
, el HAL proporciona un tiempo de espera en milisegundos. El tiempo de espera le informa al cliente que no vuelva a llamar a GateKeeper hasta que transcurra el tiempo de espera. GateKeeper no debe entregar 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 contraseña se realiza correctamente, se debe borrar el contador de fallas. Esto evita los ataques que impiden la limitación, 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 se debe limitar de la misma manera.
Si el dispositivo lo admite, se recomienda que el contador de fallas se escriba 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 el bloque de memoria protegido contra la repetición (RPMB) directamente.