Portero

El subsistema Gatekeeper realiza la autenticación de patrón/contraseña del dispositivo en un entorno de ejecución de confianza (TEE). Gatekeeper inscribe y verifica las contraseñas a través de un HMAC con una clave secreta respaldada por hardware. Además, Gatekeeper acelera los intentos de verificación fallidos consecutivos y debe rechazar las solicitudes de servicio en función de 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 atestación de autenticación para enviar 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, las claves que han creado las aplicaciones) pueden liberarse para que las usen las aplicaciones.

Arquitectura

Gatekeeper involucra tres componentes principales:

  • gatekeeperd (demonio guardián). Un servicio de enlace de C++ que contiene lógica independiente de la plataforma y correspondiente a la interfaz Java de GateKeeperService .
  • Capa de abstracción de hardware 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 basada en TEE de Gatekeeper.

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 puramente virtuales para crear/acceder a claves y computar firmas).

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

Flujo del guardián
Figura 1. Flujo de datos de alto nivel para la autenticación de GateKeeper

El daemon gatekeeperd otorga a las API del marco de trabajo de Android acceso a la HAL y participa en la notificación de autenticaciones de dispositivos al almacén de claves. El demonio gatekeeperd se ejecuta en su propio proceso y es independiente del servidor del sistema.

implementación HAL

El daemon gatekeeperd utiliza HAL para interactuar con el equivalente TEE del daemon gatekeeperd para la autenticación de contraseñas. La implementación de HAL debe poder firmar (inscribir) y verificar blobs. Se espera que todas las implementaciones se adhieran al 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 de enroll y verify :

  • La función de enroll toma un blob de contraseña, lo firma y devuelve la firma como un 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 de verify debe comparar la firma producida por la contraseña proporcionada y asegurarse de que coincida con el identificador de la contraseña inscrita.

La clave utilizada para inscribir y verificar nunca debe cambiar y debe poder volver a derivarse en cada arranque del dispositivo.

Trusty y otras implementaciones

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 usar 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 marca en suspensión .

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

La clave HMAC utilizada para inscribir y verificar contraseñas se obtiene y conserva ú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 de dispositivo para su TEE, consulte las funciones y los comentarios en system/gatekeeper/include/gatekeeper/gatekeeper.h . Para el TEE GateKeeper, las principales responsabilidades de una implementación compatible incluyen:

  • Adhesión al Gatekeeper HAL.
  • Los AuthTokens devueltos deben formatearse de acuerdo con la especificación de 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 bajo demanda o manteniendo una caché válida del valor en todo momento.

ID seguras de usuario (SID)

Un SID de usuario es la representación TEE de un usuario (sin conexión sólida con un ID de usuario de Android). El SID se genera con un generador criptográfico de números pseudoaleatorios (PRNG) cada vez que un usuario registra una nueva contraseña sin proporcionar una anterior. Esto se conoce como reinscripción no confiable y no está permitido por el marco de trabajo de Android en circunstancias normales. Una reinscripción confiable ocurre 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 de usuario se aplica a HMAC junto con la contraseña en el identificador de contraseña cuando se inscribe la contraseña.

Los SID de usuario se escriben en el AuthToken devuelto por la función de verify y se asocian a todas las claves del almacén de claves vinculadas a la autenticación (para obtener detalles sobre el formato del AuthToken y el almacén de claves, consulte Autenticación ). Como una llamada no enroll a la función de registro 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 sistema operativo Android, pero en el proceso destruirán las claves confidenciales protegidas contra la raíz.

Solicitar limitación

GateKeeper debe poder acelerar 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 las 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 tiene éxito, se debe borrar el contador de fallas. Esto evita ataques que evitan la limitación al deshabilitar la MMC integrada (eMMC) después de emitir una llamada de verify . La enroll de registro 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 enfáticamente que el contador de fallas se escriba en un almacenamiento seguro. Si el dispositivo no es compatible con el cifrado basado en archivos, o si el almacenamiento seguro es demasiado lento, las implementaciones pueden usar el bloque de memoria protegida contra reproducción (RPMB) directamente.