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 de Java estándar, consulta KeyGenParameterSpec
).
Glosario
A continuación, se incluye una descripción general rápida de los componentes de Keystore y sus relaciones.
AndroidKeyStore
- Es 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 propio de la app.
AndroidKeyStore
satisface 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
- Es un daemon del sistema Android que proporciona acceso a toda la funcionalidad 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
y proporciona acceso al TA de KeyMint subyacente. - App de confianza (TA) de KeyMint
- Software que se ejecuta en un contexto seguro, por lo general, en TrustZone en un SoC de ARM, que proporciona todas las operaciones criptográficas seguras. Esta app tiene acceso al material de claves sin procesar y valida todas las condiciones de control de acceso en las claves antes de permitir su uso.
LockSettingsService
- 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 solo se pueden usar si el usuario se autenticó.
LockSettingsService
interactúa con la TA de Gatekeeper y la TA de Fingerprint para obtener tokens de autenticación, que proporciona al daemon de KeyStore 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 de los usuarios y generar los tokens de autenticación que se usan para demostrarle a la TA de KeyMint que se realizó una autenticación para un usuario en particular en un momento específico.
- TA de huella dactilar
- Es 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 a la TA de KeyMint que se realizó una autenticación para un usuario en particular en un momento específico.
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 que usan claves respaldadas por hardware y controladas por acceso.
El HAL de KeyMint es un servicio proporcionado por el OEM que usa el servicio de Keystore para proporcionar servicios criptográficos respaldados por hardware. Para mantener seguro el material de la clave privada, 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, serializando y deserializando solicitudes en algún formato de cable definido por la implementación.
La arquitectura resultante se ve de la siguiente manera:

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 creó la clave.
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 clave. 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
de Keystore. También se incluye el UID de la entidad que realiza la llamada para desambiguar las claves de diferentes apps, lo que evita que una app acceda a las claves de otra.
Internamente, 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 sigue funcionando: incluso si una app descubre el ID de clave de otra app, no puede usarlo en circunstancias normales.
Sin embargo, es posible que una app otorgue el uso de una clave a otra app (identificada por el UID). Esta operación de concesión devuelve un identificador único de concesión, 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 app de terceros descubre el ID de concesión de la clave de un beneficiario, no puede usarlo.
Keystore también admite otros dos dominios para los descriptores de claves, que se usan para otros componentes del sistema y no están disponibles para las claves creadas por la app:
- El dominio
BLOB
indica que no hay un identificador para la clave en el descriptor de claves; en cambio, el descriptor de claves contiene el keyblob en sí y el cliente controla el almacenamiento del keyblob. Los clientes (por ejemplo,vold
) que necesitan acceder a Keystore antes de que se monte la partición de datos usan este valor. - El dominio
SELINUX
permite que los componentes del sistema compartan claves, y el acceso se rige por un identificador numérico que corresponde a una etiqueta de SELinux (consulta 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 clave 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 necesita acceder 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 | 0 … 9,999 | /system/etc/selinux/keystore2_key_contexts, /plat_keystore2_key_contexts
|
Sistema extendido | 10,000 … 19,999 | /system_ext/etc/selinux/system_ext_keystore2_key_contexts, /system_ext_keystore2_key_contexts
|
Producto | 20,000 … 29,999 | /product/etc/selinux/product_keystore2_key_contexts, /product_keystore2_key_contexts
|
Proveedor | 30,000 … 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 | Es la clave de superusuario. Solo se usa para pruebas en compilaciones de userdebug y eng. No es relevante en las compilaciones del usuario. |
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 de usuarios desde la línea de comandos. |
100 | vold_key |
N/A | Está diseñado para que lo use vold. |
101 | odsign_key |
N/A | Lo usa el daemon de firma integrado en el dispositivo. |
102 | wifi_key |
AID_WIFI(1010) |
El subsistema de Wi-Fi de Android lo usa, 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 Política de SELinux para keystore_key, en la siguiente tabla, se describen otros permisos de SELinux que son necesarios para realizar diversas operaciones de mantenimiento y del sistema:
Permiso | Significado |
---|---|
add_auth
|
Se requiere para agregar tokens de autorización a Keystore. Los proveedores de autenticación, como Gatekeeper o BiometricManager , lo usan. |
clear_ns
|
Se requiere para borrar todas las claves de un espacio de nombres específico y se usa como operación de mantenimiento cuando se desinstalan apps. |
list
|
El sistema lo requiere para enumerar las 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 (cubierto por el permiso get_info ). |
lock
|
Se requiere 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
|
Se requiere para notificar al almacén de claves que se desbloqueó el dispositivo y restablecer el acceso a las superclaves que protegen las claves vinculadas a la autenticación. |
reset
|
Se requiere 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 criptográficos simple y 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. Operaciones de firma y verificación digitales proporcionadas por el almacén de claves, además de la generación e importación de pares de claves de firma asimétricas. Esto ya se implementó en muchos dispositivos, pero hay muchos objetivos de seguridad que no se pueden lograr fácilmente solo con una API de firma. Android 6.0 extendió la API de Keystore para proporcionar una gama más amplia de capacidades.
Android 6.0
En Android 6.0, Keymaster 1.0 agregó primitivas criptográficas simétricas, AES y HMAC, y un sistema de control de acceso para claves respaldadas por hardware. Los controles de acceso se especifican durante la generación de la clave y se aplican durante toda su vida útil. Las claves se pueden restringir para que solo se puedan usar después de que el usuario se haya autenticado y solo para fines específicos o con parámetros criptográficos específicos.
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
- Es un esquema de control de acceso para permitir 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 versión 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 recientes, 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 queden inutilizables.
Android 8.0
En Android 8.0, Keymaster 3 realizó la transición de la 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 struct de 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 adició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 alguna forma segura de recuperar los elementos de datos pertinentes, 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 integrados
- 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 de la 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 del arranque
- Compatibilidad opcional con claves de almacenamiento protegidas por hardware
- Compatibilidad opcional con la certificación única del dispositivo en StrongBox
Android 12
Android 12 introdujo la nueva HAL de KeyMint, que reemplaza a 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 keystore, reescrito en Rust y conocido 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.