La disponibilidad de un entorno de ejecución confiable (TEE) en un sistema en un chip (SoC) ofrece una oportunidad para que los dispositivos Android proporcionen servicios de seguridad sólidos respaldados por hardware al SO Android, a los servicios de la plataforma y hasta a las apps de terceros (en forma de extensiones específicas de Android para la arquitectura de criptografía estándar de Java, consulta KeyGenParameterSpec
).
Glosario
A continuación, se incluye una descripción general rápida de los componentes del almacén de claves y sus relaciones.
AndroidKeyStore
- La API y el componente de Android Framework que usan las apps para acceder a la funcionalidad de Keystore. Es una implementación de las APIs estándar de la arquitectura de criptografía de Java, pero también agrega extensiones específicas de Android y consta de código Java que se ejecuta en el espacio de proceso de la app.
AndroidKeyStore
entrega las solicitudes de la app para el comportamiento del almacén de claves reenviándolas al daemon del almacén de claves. - daemon de almacén de claves
- Un daemon del sistema Android que proporciona acceso a todas las funciones de Keystore a través de una API de Binder. Este daemon es responsable de almacenar los keyblobs creados por la implementación subyacente de KeyMint (o Keymaster), que contienen el material de clave secreta, encriptado para que el almacén de claves pueda almacenarlos, pero no usarlos ni revelarlos.
- Servicio de HAL de KeyMint
- Un servidor de AIDL que implementa la HAL de
IKeyMintDevice
, lo que proporciona acceso al TA de KeyMint subyacente. - App de confianza (TA) de KeyMint
- Software que se ejecuta en un contexto seguro, con mayor frecuencia en TrustZone en un SoC ARM, que proporciona todas las operaciones criptográficas seguras. Esta app tiene acceso al material de clave sin procesar y valida todas las condiciones de control de acceso en las claves antes de permitir su uso.
LockSettingsService
- El componente del sistema Android responsable de la autenticación del usuario, tanto con contraseña como con huella dactilar. No forma parte de Keystore, pero es relevante porque Keystore admite el concepto de claves vinculadas a la autenticación: claves que se pueden usar solo si el usuario se autenticó.
LockSettingsService
interactúa con la TA de Gatekeeper y la de Fingerprint para obtener tokens de autenticación, que proporciona al daemon del almacén de claves y que consume la TA de KeyMint. - TA de Gatekeeper
- Es el componente que se ejecuta en el entorno seguro y que se encarga de autenticar las contraseñas del usuario y generar tokens de autenticación que se usan para demostrarle al TA de KeyMint que se realizó una autenticación para un usuario en particular en un momento determinado.
- TA de huellas dactilares
- El componente que se ejecuta en el entorno seguro y que es responsable de autenticar las huellas dactilares del usuario y generar tokens de autenticación que se usan para demostrarle al TA de KeyMint que se realizó una autenticación para un usuario en particular en un momento determinado.
Arquitectura
La API de Android Keystore y el HAL de KeyMint subyacente proporcionan un conjunto básico, pero adecuado, de primitivas criptográficas para permitir la implementación de protocolos con claves respaldadas por hardware y controladas por acceso.
El HAL de KeyMint es un servicio proporcionado por el OEM que usa el servicio de almacén de claves para proporcionar servicios criptográficos respaldados por hardware. Para mantener el material de la clave privada seguro, las implementaciones de HAL no realizan ninguna operación sensible en el espacio del usuario ni en el espacio del kernel. En su lugar, el servicio de HAL de KeyMint que se ejecuta en Android delega las operaciones sensibles a un TA que se ejecuta en algún tipo de entorno seguro, por lo general, mediante el agrupamiento y el desagrupamiento de solicitudes en algún formato de cable definido por la implementación.
La arquitectura resultante se ve así:

Figura 1: Acceso a KeyMint
La API de HAL de KeyMint es de bajo nivel, la usan los componentes internos de la plataforma y no se expone a los desarrolladores de apps. La API de Java de nivel superior que está disponible para las apps se describe en el sitio para desarrolladores de Android.
Control de acceso
Android Keystore proporciona un componente central para el almacenamiento y el uso de claves criptográficas respaldadas por hardware, tanto para apps como para otros componentes del sistema. Por lo tanto, el acceso a cualquier clave individual suele limitarse a la app o al componente del sistema que la creó.
Dominios del almacén de claves
Para admitir este control de acceso, las claves se identifican en el almacén de claves con un descriptor de claves. Este descriptor de clave indica un dominio al que pertenece el descriptor, junto con una identidad dentro de ese dominio.
Las apps para Android acceden a Keystore con la Arquitectura de criptografía de Java estándar, que identifica las claves con un alias de cadena. Este método de identificación se asigna internamente al dominio APP
del almacén de claves. También se incluye el UID del llamador para desambiguar las claves de diferentes apps, lo que evita que una app acceda a las claves de otra.
De forma interna, el código de los frameworks también recibe un ID de clave numérico único después de que se carga una clave. Este ID numérico se usa como identificador para los descriptores de claves dentro del dominio KEY_ID
. Sin embargo, el control de acceso se sigue realizando: incluso si una app descubre un ID de clave para la clave de otra app, no puede usarlo en circunstancias normales.
Sin embargo, es posible que una app otorgue el uso de una clave a una app diferente (como lo identifica el UID). Esta operación de otorgamiento muestra un identificador de otorgamiento único, que se usa como identificador para los descriptores de claves dentro del dominio GRANT
. Una vez más, se sigue realizando el control de acceso: incluso si una tercera app descubre el ID de otorgamiento de la clave de un beneficiario, no puede usarlo.
El almacén de claves también admite otros dos dominios para descriptores de claves, que se usan para otros componentes del sistema y no están disponibles para las claves creadas por apps:
- El dominio
BLOB
indica que no hay un identificador para la clave en el descriptor de claves. En su lugar, el descriptor de claves contiene el propio keyblob, y el cliente controla el almacenamiento de keyblob. Los clientes (por ejemplo,vold
) que necesitan acceder al almacén de claves antes de que se active la partición de datos usan esta función. - El dominio
SELINUX
permite que los componentes del sistema compartan claves, con acceso gobernado por un identificador numérico que corresponde a una etiqueta de SELinux (consulta la política de SELinux para keystore_key).
Política de SELinux para keystore_key
Los valores de identificador que se usan para los descriptores de claves Domain::SELINUX
se configuran en el archivo de política de SELinux keystore2_key_context
.
Cada línea de estos archivos asigna un valor numérico a una etiqueta de SELinux, por ejemplo:
# wifi_key is a keystore2_key namespace intended to be used by wpa supplicant and # Settings to share Keystore keys. 102 u:object_r:wifi_key:s0
Un componente que necesite acceso a la clave con el ID 102 en el dominio SELINUX
debe tener la política de SELinux correspondiente. Por ejemplo, para permitir que wpa_supplicant
obtenga y use estas claves, agrega la siguiente línea a hal_wifi_supplicant.te
:
allow hal_wifi_supplicant wifi_key:keystore2_key { get, use };
Los identificadores numéricos de las claves Domain::SELINUX
se dividen en rangos para admitir diferentes particiones sin colisiones:
Partición | Rango | Archivos de configuración |
---|---|---|
Sistema | De 0 a 9,999 | /system/etc/selinux/keystore2_key_contexts, /plat_keystore2_key_contexts
|
Sistema extendido | Entre 10,000 y 19,999 | /system_ext/etc/selinux/system_ext_keystore2_key_contexts, /system_ext_keystore2_key_contexts
|
Producto | 20,000 a 29,999 | /product/etc/selinux/product_keystore2_key_contexts, /product_keystore2_key_contexts
|
Proveedor | 30,000 a 39,999 | /vendor/etc/selinux/vendor_keystore2_key_contexts, /vendor_keystore2_key_contexts
|
Se definieron los siguientes valores específicos para la partición del sistema:
ID del espacio de nombres | Etiqueta de SEPolicy | UID | Descripción |
---|---|---|---|
0 | su_key |
N/A | Clave de superusuario Solo se usa para pruebas en compilaciones de userdebug y eng. No es relevante en compilaciones de usuarios. |
1 | shell_key |
N/A | Es el espacio de nombres disponible para la shell. Se usa principalmente para pruebas, pero también se puede usar en compilaciones del usuario desde la línea de comandos. |
100 | vold_key |
N/A | Está diseñado para que lo use vold. |
101 | odsign_key |
N/A | Es usado por el daemon de firma integrado en el dispositivo. |
102 | wifi_key |
AID_WIFI(1010) |
Es usado por el subsistema de Wi-Fi de Android, incluido wpa_supplicant . |
103 | locksettings_key |
N/A | Usado por LockSettingsService |
120 | resume_on_reboot_key |
AID_SYSTEM(1000) |
El servidor del sistema de Android lo usa para admitir la reanudación en el reinicio. |
Vectores de acceso
El almacén de claves permite controlar qué operaciones se pueden realizar en una clave, además de controlar el acceso general a una clave. Los permisos de keystore2_key
se describen en el archivo KeyPermission.aidl
.
Permisos del sistema
Además de los controles de acceso por clave que se describen en la política de SELinux para keystore_key, en la siguiente tabla se describen otros permisos de SELinux que se requieren para realizar varias operaciones de mantenimiento y del sistema:
Permiso | Significado |
---|---|
add_auth
|
Es obligatorio para agregar tokens de autenticación al almacén de claves. Los proveedores de autenticación, como Gatekeeper o BiometricManager , lo usan. |
clear_ns
|
Obligatorio para borrar todas las claves de un espacio de nombres específico. Se usa como operación de mantenimiento cuando se desinstalan las apps. |
list
|
El sistema lo requiere para enumerar claves por varias propiedades, como la propiedad o si están vinculadas a la autenticación. Los llamadores que enumeran sus propios espacios de nombres no requieren este permiso (que se incluye en el permiso get_info ). |
lock
|
Es obligatorio para notificar al almacén de claves que el dispositivo se bloqueó, lo que, a su vez, expulsa las superclaves para garantizar que las claves vinculadas a la autenticación no estén disponibles. |
unlock
|
Es obligatorio notificar al almacén de claves que el dispositivo se desbloqueó y restablecer el acceso a las superclaves que protegen las claves vinculadas de autenticación. |
reset
|
Es obligatorio para restablecer el almacén de claves a la configuración predeterminada de fábrica y borrar todas las claves que no son vitales para el funcionamiento del SO Android. |
Historial
En Android 5 y versiones anteriores, Android tenía una API de servicios de criptografía simple con copia de seguridad en hardware, proporcionada por las versiones 0.2 y 0.3 de la capa de abstracción de hardware (HAL) de Keymaster. El almacén de claves proporcionaba operaciones de firma y verificación digitales, además de la generación e importación de pares de claves de firma asimétrica. Esto ya está implementado en muchos dispositivos, pero hay muchos objetivos de seguridad que no se pueden lograr fácilmente con solo una API de firma. Android 6.0 amplió la API de Keystore para proporcionar una gama más amplia de capacidades.
Android 6.0
En Android 6.0, Keymaster 1.0 agregó primitivos de criptografía simétrica, AES y HMAC, y un sistema de control de acceso para claves con copia de seguridad en hardware. Los controles de acceso se especifican durante la generación de claves y se aplican durante toda su vida útil. Las claves se pueden restringir para que solo se puedan usar después de que se haya autenticado al usuario y solo para fines o parámetros criptográficos especificados.
Además de expandir el rango de primitivas criptográficas, Keystore en Android 6.0 agregó lo siguiente:
- Un esquema de control de uso para permitir que se limite el uso de claves y mitigar el riesgo de vulneración de la seguridad debido al uso inadecuado de las claves
- Un esquema de control de acceso para habilitar la restricción de claves a usuarios, clientes y un período definidos
Android 7.0
En Android 7.0, Keymaster 2 agregó compatibilidad con la certificación de claves y la vinculación de versiones.
La certificación de claves proporciona certificados de clave pública que contienen una descripción detallada de la clave y sus controles de acceso para que la existencia de la clave en hardware seguro y su configuración se puedan verificar de forma remota.
La vinculación de versiones vincula las claves al sistema operativo y a la versión del nivel de parche. Esto garantiza que un atacante que descubra una debilidad en una versión anterior del sistema o del software del TEE no pueda revertir un dispositivo a la versión vulnerable y usar las claves creadas con la versión más reciente. Además, cuando se usa una clave con una versión y un nivel de parche determinados en un dispositivo que se actualizó a una versión o un nivel de parche más reciente, la clave se actualiza antes de que se pueda usar y se invalida la versión anterior de la clave. A medida que se actualiza el dispositivo, las claves avanzan junto con él, pero cualquier reversión del dispositivo a una versión anterior hace que las claves no se puedan usar.
Android 8.0
En Android 8.0, Keymaster 3 realizó la transición del HAL de estructura C de estilo antiguo a la interfaz de HAL de C++ generada a partir de una definición en el nuevo lenguaje de definición de interfaz de hardware (HIDL). Como parte del cambio, muchos de los tipos de argumentos cambiaron, aunque los tipos y los métodos tienen una correspondencia uno a uno con los tipos anteriores y los métodos de la estructura HAL.
Además de esta revisión de la interfaz, Android 8.0 extendió la función de certificación de Keymaster 2 para admitir la certificación de ID. La certificación de ID proporciona un mecanismo limitado y opcional para certificar de forma sólida los identificadores de hardware, como el número de serie del dispositivo, el nombre del producto y el ID del teléfono (IMEI o MEID). Para implementar esta incorporación, Android 8.0 cambió el esquema de certificación ASN.1 para agregar la certificación de ID. Las implementaciones de Keymaster deben encontrar una forma segura de recuperar los elementos de datos relevantes, así como definir un mecanismo para inhabilitar la función de forma segura y permanente.
Android 9
En Android 9, las actualizaciones incluyeron lo siguiente:
- Actualización a Keymaster 4
- Compatibilidad con elementos seguros incorporados
- Compatibilidad con la importación de claves seguras
- Compatibilidad con la encriptación 3DES
- Se realizaron cambios en la vinculación de versiones para que
boot.img
ysystem.img
tengan versiones configuradas por separado para permitir actualizaciones independientes.
Android 10
Android 10 introdujo la versión 4.1 del HAL de Keymaster, que agregó lo siguiente:
- Compatibilidad con llaves que solo se pueden usar cuando el dispositivo está desbloqueado
- Compatibilidad con claves que solo se pueden usar en las primeras etapas de inicio
- Compatibilidad opcional con llaves de almacenamiento combinadas con hardware
- Compatibilidad opcional con la certificación única del dispositivo en StrongBox
Android 12
Android 12 presentó la nueva HAL de KeyMint, que reemplaza la HAL de Keymaster, pero proporciona una funcionalidad similar. Además de todas las funciones anteriores, el HAL de KeyMint también incluye lo siguiente:
- Compatibilidad con el acuerdo de claves ECDH
- Compatibilidad con claves de certificación especificadas por el usuario
- Compatibilidad con claves con una cantidad limitada de usos
Android 12 también incluye una nueva versión del daemon del sistema de almacén de claves, que se volvió a escribir en Rust y se conoce como keystore2
.
Android 13
Android 13 agregó la versión 2 de la HAL de KeyMint, que agrega compatibilidad con Curve25519 para la firma y el acuerdo de claves.