Encriptación basada en archivos

Android 7.0 y versiones posteriores admiten la encriptación basada en archivos (FBE). La encriptación basada en archivos permite encriptar diferentes archivos con distintas claves que se pueden desbloquear de forma independiente.

En este artículo, se describe cómo habilitar la encriptación basada en archivos en dispositivos nuevos y cómo las apps del sistema pueden usar las APIs de inicio directo para ofrecer a los usuarios la mejor experiencia posible y la más segura.

Todos los dispositivos que se lanzan con Android 10 y versiones posteriores deben usar la encriptación basada en archivos.

Modo de inicio directo

La encriptación basada en archivos habilita una nueva función que se introdujo en Android 7.0, llamada Inicio directo. El inicio directo permite que los dispositivos encriptados se inicien directamente en la pantalla de bloqueo. Anteriormente, en los dispositivos encriptados con encriptación de disco completo (FDE), los usuarios debían proporcionar credenciales antes de que se pudiera acceder a los datos, lo que impedía que el teléfono realizara todas las operaciones, excepto las más básicas. Por ejemplo, las alarmas no podían funcionar, los servicios de accesibilidad no estaban disponibles y los teléfonos no podían recibir llamadas, sino que se limitaban solo a las operaciones básicas del marcador de emergencia.

Con la introducción de la encriptación basada en archivos (FBE) y las nuevas APIs para que las apps reconozcan la encriptación, es posible que estas apps funcionen en un contexto limitado. Esto puede ocurrir antes de que los usuarios proporcionen sus credenciales, sin dejar de proteger la información privada del usuario.

En un dispositivo con FBE habilitada, cada usuario tiene dos ubicaciones de almacenamiento disponibles para las apps:

  • Almacenamiento encriptado por credenciales (CE), que es la ubicación de almacenamiento predeterminada y solo está disponible después de que el usuario desbloquea el dispositivo.
  • Almacenamiento encriptado por dispositivo (DE), que es una ubicación de almacenamiento disponible tanto durante el modo de inicio directo como después de que el usuario desbloquea el dispositivo.

Esta separación hace que los perfiles de trabajo sean más seguros, ya que permite proteger a más de un usuario a la vez, dado que la encriptación ya no se basa únicamente en una contraseña de tiempo de inicio.

La API de inicio directo permite que las apps que reconocen la encriptación accedan a cada una de estas áreas. Se realizaron cambios en el ciclo de vida de la app para adaptarse a la necesidad de notificar a las apps cuando el almacenamiento de CE de un usuario se desbloquea en respuesta al primer ingreso de credenciales en la pantalla de bloqueo o, en el caso del perfil de trabajo, cuando se proporciona un desafío de trabajo. Los dispositivos que ejecutan Android 7.0 deben admitir estas nuevas APIs y ciclos de vida, independientemente de si implementan o no la FBE. Sin embargo, sin FBE, el almacenamiento DE y CE siempre están en estado desbloqueado.

En el Proyecto de código abierto de Android (AOSP), se proporciona una implementación completa de la encriptación basada en archivos en los sistemas de archivos Ext4 y F2FS, y solo debe habilitarse en los dispositivos que cumplan con los requisitos. Los fabricantes que decidan usar la FBE pueden explorar formas de optimizar la función según el sistema en chip (SoC) que se use.

Todos los paquetes necesarios en el AOSP se actualizaron para que sean compatibles con el inicio directo. Sin embargo, cuando los fabricantes de dispositivos usan versiones personalizadas de estas apps, quieren asegurarse de que, como mínimo, haya paquetes compatibles con el inicio directo que proporcionen los siguientes servicios:

  • Servicios de telefonía y marcador
  • Es el método de entrada para ingresar contraseñas en la pantalla de bloqueo.

Ejemplos y fuente

Android proporciona una implementación de referencia de la encriptación basada en archivos, en la que vold (system/vold) proporciona la funcionalidad para administrar dispositivos de almacenamiento y volúmenes en Android. La incorporación de la FBE proporciona a vold varios comandos nuevos para admitir la administración de claves de las claves de CE y DE de varios usuarios. Además de los cambios principales para usar las capacidades de encriptación basada en archivos en el kernel, se modificaron muchos paquetes del sistema, como la pantalla de bloqueo y la SystemUI, para admitir las funciones de FBE y de inicio directo. Por ejemplo:

  • Marcador de AOSP (packages/apps/Dialer)
  • Reloj de escritorio (packages/apps/DeskClock)
  • LatinIME (packages/inputmethods/LatinIME)*
  • App de Configuración (packages/apps/Settings)*
  • SystemUI (frameworks/base/packages/SystemUI)*

* Apps del sistema que usan el atributo de manifiesto defaultToDeviceProtectedStorage

Para encontrar más ejemplos de apps y servicios que reconocen la encriptación, ejecuta el comando mangrep directBootAware en el directorio de frameworks o paquetes del árbol de fuentes del AOSP.

Dependencias

Para usar la implementación de FBE del AOSP de forma segura, un dispositivo debe cumplir con las siguientes dependencias:

  • Compatibilidad con el kernel para la encriptación Ext4 o F2FS
  • Compatibilidad con KeyMint (o Keymaster 1.0 o versiones posteriores). No se admite Keymaster 0.3, ya que no proporciona las capacidades necesarias ni garantiza una protección suficiente para las claves de encriptación.
  • KeyMint/Keymaster y Gatekeeper se deben implementar en un entorno de ejecución confiable (TEE) para proteger las claves de DE, de modo que un SO no autorizado (SO personalizado que se instala en el dispositivo) no pueda simplemente solicitar las claves de DE.
  • Se requiere una raíz de confianza de hardware y un inicio verificado vinculados a la inicialización de KeyMint para garantizar que un sistema operativo no autorizado no pueda acceder a las claves de DE.

Implementación

En primer lugar, las apps como los relojes de alarma, el teléfono y las funciones de accesibilidad deben ser android:directBootAware según la documentación para desarrolladores de Direct Boot.

Compatibilidad con kernel

La compatibilidad del kernel con la encriptación Ext4 y F2FS está disponible en los kernels comunes de Android, versión 3.18 y posteriores. Para habilitarlo en un kernel que sea de la versión 5.1 o posterior, usa lo siguiente:

CONFIG_FS_ENCRYPTION=y

Para kernels más antiguos, usa CONFIG_EXT4_ENCRYPTION=y si el sistema de archivos userdata de tu dispositivo es Ext4, o bien usa CONFIG_F2FS_FS_ENCRYPTION=y si el sistema de archivos userdata de tu dispositivo es F2FS.

Si tu dispositivo admite el almacenamiento adoptable o usa la encriptación de metadatos en el almacenamiento interno, habilita también las opciones de configuración del kernel necesarias para la encriptación de metadatos, como se describe en la documentación de encriptación de metadatos.

Además de la compatibilidad funcional con la encriptación Ext4 o F2FS, los fabricantes de dispositivos también deben habilitar la aceleración criptográfica para acelerar la encriptación basada en archivos y mejorar la experiencia del usuario. Por ejemplo, en los dispositivos basados en ARM64, la aceleración de ARMv8 CE (extensiones de criptografía) se puede habilitar configurando las siguientes opciones de configuración del kernel:

CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
CONFIG_CRYPTO_SHA2_ARM64_CE=y

Para mejorar aún más el rendimiento y reducir el uso de energía, los fabricantes de dispositivos también pueden considerar implementar un hardware de encriptación intercalado, que encripta y desencripta los datos mientras se dirigen hacia el dispositivo de almacenamiento o desde él. Los kernels comunes de Android (versión 4.14 y posteriores) contienen un framework que permite usar la encriptación intercalada cuando hay compatibilidad con el hardware y el controlador del proveedor. El framework de encriptación intercalada se puede habilitar configurando las siguientes opciones de configuración del kernel:

CONFIG_BLK_INLINE_ENCRYPTION=y
CONFIG_FS_ENCRYPTION=y
CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y

Si tu dispositivo usa almacenamiento basado en UFS, habilita también lo siguiente:

CONFIG_SCSI_UFS_CRYPTO=y

Si tu dispositivo usa almacenamiento basado en eMMC, habilita también lo siguiente:

CONFIG_MMC_CRYPTO=y

Habilita la encriptación basada en archivos

Para habilitar la FBE en un dispositivo, se debe habilitar en el almacenamiento interno (userdata). Esto también habilita automáticamente la FBE en el almacenamiento adoptable. Sin embargo, el formato de encriptación en el almacenamiento adoptable se puede anular si es necesario.

Almacenamiento interno

La FBE se habilita agregando la opción fileencryption=contents_encryption_mode[:filenames_encryption_mode[:flags]] a la columna fs_mgr_flags de la línea fstab para userdata. Esta opción define el formato de encriptación en el almacenamiento interno. Contiene hasta tres parámetros separados por dos puntos:

  • El parámetro contents_encryption_mode define qué algoritmo criptográfico se usa para encriptar el contenido del archivo. Puede ser aes-256-xts o adiantum. Desde Android 11, también se puede dejar vacío para especificar el algoritmo predeterminado, que es aes-256-xts.
  • El parámetro filenames_encryption_mode define qué algoritmo criptográfico se usa para encriptar los nombres de los archivos. Puede ser aes-256-cts, aes-256-heh, adiantum o aes-256-hctr2. Si no se especifica, el valor predeterminado es aes-256-cts si contents_encryption_mode es aes-256-xts, o adiantum si contents_encryption_mode es adiantum.
  • El parámetro flags, nuevo en Android 11, es una lista de marcas separadas por el carácter +. Se admiten las siguientes marcas:
    • La marca v1 selecciona las políticas de encriptación de la versión 1, y la marca v2 selecciona las políticas de encriptación de la versión 2. Las políticas de encriptación de la versión 2 usan una función de derivación de claves más segura y flexible. El valor predeterminado es v2 si el dispositivo se lanzó con Android 11 o una versión posterior (según lo determine ro.product.first_api_level), o v1 si el dispositivo se lanzó con Android 10 o una versión anterior.
    • La marca inlinecrypt_optimized selecciona un formato de encriptación optimizado para el hardware de encriptación intercalada que no controla grandes cantidades de claves de manera eficiente. Para ello, deriva solo una clave de encriptación de contenido de archivo por clave de CE o DE, en lugar de una por archivo. La generación de IV (vectores de inicialización) se ajusta según corresponda.
    • La marca emmc_optimized es similar a inlinecrypt_optimized, pero también selecciona un método de generación de IV que limita los IV a 32 bits. Esta marca solo debe usarse en hardware de encriptación intercalada que cumpla con la especificación JEDEC eMMC v5.2 y, por lo tanto, solo admita IV de 32 bits. En otro hardware de encriptación intercalada, usa inlinecrypt_optimized en su lugar. Esta marca nunca se debe usar en el almacenamiento basado en UFS; la especificación de UFS permite el uso de IV de 64 bits.
    • En los dispositivos que admiten claves de encriptación intercaladas unidas por hardware, las claves de FBE se pueden unir por hardware agregando la marca wrappedkey o wrappedkey_v0. wrappedkey es la versión moderna; wrappedkey_v0 solo se debe usar en dispositivos que no admiten wrappedkey o que ya se lanzaron con wrappedkey_v0. Para obtener más información, consulta Habilita claves unidas.
    • La marca dusize_4k fuerza el tamaño de la unidad de datos de encriptación para que sea de 4,096 bytes, incluso cuando el tamaño del bloque del sistema de archivos no sea de 4,096 bytes. El tamaño de la unidad de datos de encriptación es el nivel de detalle de la encriptación del contenido del archivo. Esta marca está disponible desde Android 15. Esta marca solo se debe usar para habilitar el uso de hardware de encriptación intercalada que no admite unidades de datos superiores a 4,096 bytes en un dispositivo que usa un tamaño de página superior a 4,096 bytes y que usa el sistema de archivos f2fs.

Si no usas hardware de encriptación intercalada, el parámetro de configuración recomendado para la mayoría de los dispositivos es fileencryption=aes-256-xts. Si usas hardware de encriptación intercalada, el parámetro de configuración recomendado para la mayoría de los dispositivos es fileencryption=aes-256-xts:aes-256-cts:inlinecrypt_optimized (o, de manera equivalente, fileencryption=::inlinecrypt_optimized). En los dispositivos sin ningún tipo de aceleración de AES, se puede usar Adiantum en lugar de AES configurando fileencryption=adiantum.

Desde Android 14, AES-HCTR2 es el modo preferido de encriptación de nombres de archivo para dispositivos con instrucciones de criptografía acelerada. Sin embargo, solo los kernels de Android más recientes admiten AES-HCTR2. En una versión futura de Android, se planea que se convierta en el modo predeterminado para la encriptación de nombres de archivos. Si tu kernel es compatible con AES-HCTR2, se puede habilitar para la encriptación de nombres de archivo estableciendo filenames_encryption_mode en aes-256-hctr2. En el caso más simple, esto se haría con fileencryption=aes-256-xts:aes-256-hctr2.

En los dispositivos que se lanzaron con Android 10 y versiones anteriores, también se acepta fileencryption=ice para especificar el uso del modo de encriptación de contenido de archivos FSCRYPT_MODE_PRIVATE. Los kernels comunes de Android no implementan este modo, pero los proveedores podrían implementarlo con parches de kernel personalizados. El formato en el disco que producía este modo era específico del proveedor. En los dispositivos que se lanzan con Android 11 o versiones posteriores, ya no se permite este modo y, en su lugar, se debe usar un formato de encriptación estándar.

De forma predeterminada, la encriptación del contenido de los archivos se realiza con la API de criptografía del kernel de Linux. Si, en cambio, quieres usar hardware de encriptación intercalada, agrega también la opción de activación inlinecrypt. Por ejemplo, una línea fstab completa podría verse de la siguiente manera:

/dev/block/by-name/userdata /data f2fs nodev,noatime,nosuid,errors=panic,inlinecrypt wait,fileencryption=aes-256-xts:aes-256-cts:inlinecrypt_optimized

Almacenamiento adoptable

Desde Android 9, la FBE y el almacenamiento adoptable se pueden usar juntos.

Especificar la opción fstab fileencryption para userdata también habilita automáticamente la FBE y la encriptación de metadatos en el almacenamiento adoptable. Sin embargo, puedes anular los formatos de encriptación de metadatos o FBE en el almacenamiento adoptable configurando las propiedades en PRODUCT_PROPERTY_OVERRIDES.

En los dispositivos que se lanzaron con Android 11 o versiones posteriores, usa las siguientes propiedades:

  • ro.crypto.volume.options (nuevo en Android 11) selecciona el formato de encriptación de FBE en el almacenamiento adoptable. Tiene la misma sintaxis que el argumento de la opción fileencryption fstab y usa los mismos valores predeterminados. Consulta las recomendaciones para fileencryption que se indican más arriba para saber qué usar aquí.
  • ro.crypto.volume.metadata.encryption selecciona el formato de encriptación de metadatos en el almacenamiento adoptable. Consulta la documentación sobre la encriptación de metadatos.

En los dispositivos que se lanzaron con Android 10 y versiones anteriores, usa las siguientes propiedades:

  • ro.crypto.volume.contents_mode selecciona el modo de encriptación del contenido. Esto equivale al primer campo separado por dos puntos de ro.crypto.volume.options.
  • ro.crypto.volume.filenames_mode selecciona el modo de encriptación de los nombres de archivo. Esto equivale al segundo campo separado por dos puntos de ro.crypto.volume.options, excepto que el valor predeterminado en los dispositivos que se lanzaron con Android 10 y versiones anteriores es aes-256-heh. En la mayoría de los dispositivos, esto se debe anular de forma explícita a aes-256-cts.
  • ro.crypto.fde_algorithm y ro.crypto.fde_sector_size seleccionan el formato de encriptación de metadatos en el almacenamiento adoptable. Consulta la documentación sobre la encriptación de metadatos.

Integración con KeyMint

La HAL de KeyMint se debe iniciar como parte de la clase early_hal. Esto se debe a que la FBE requiere que KeyMint esté listo para controlar las solicitudes en la fase de inicio post-fs-data, que es cuando vold configura las claves iniciales.

Excluye directorios

init aplica la clave de DE del sistema a todos los directorios de nivel superior de /data, excepto los directorios que deben estar sin encriptar, como el directorio que contiene la clave de DE del sistema y los directorios que contienen directorios de CE o DE del usuario. Las claves de encriptación se aplican de forma recurrente y los subdirectorios no pueden anularlas.

En Android 11 y versiones posteriores, la clave que init aplica a los directorios se puede controlar con el argumento encryption=<action> del comando mkdir en las secuencias de comandos de inicio. Los valores posibles de <action> se documentan en el archivo README para el lenguaje de inicialización de Android.

En Android 10, las acciones de encriptación de init se codificaron en la siguiente ubicación:

/system/extras/libfscrypt/fscrypt_init_extensions.cpp

En Android 9 y versiones anteriores, la ubicación era la siguiente:

/system/extras/ext4_utils/ext4_crypt_init_extensions.cpp

Es posible agregar excepciones para evitar que se encripten ciertos directorios. Si se realizan modificaciones de este tipo, el fabricante del dispositivo debe incluir políticas de SELinux que solo otorguen acceso a las apps que necesitan usar el directorio sin encriptar. Esto debería excluir todas las apps no confiables.

El único caso de uso aceptable conocido para esto es la compatibilidad con las funciones de OTA heredadas.

Cómo brindar compatibilidad con el inicio directo en las apps del sistema

Cómo hacer que las apps reconozcan el inicio directo

Para facilitar la migración rápida de las apps del sistema, hay dos atributos nuevos que se pueden establecer a nivel de la app. El atributo defaultToDeviceProtectedStorage solo está disponible para las apps del sistema. El atributo directBootAware está disponible para todos los usuarios.

<application
    android:directBootAware="true"
    android:defaultToDeviceProtectedStorage="true">

El atributo directBootAware a nivel de la app es una forma abreviada de marcar todos los componentes de la app como con reconocimiento de encriptación.

El atributo defaultToDeviceProtectedStorage redirecciona la ubicación de almacenamiento predeterminada de la app para que apunte al almacenamiento DE en lugar del almacenamiento CE. Las apps del sistema que usen este parámetro deben auditar con cuidado todos los datos almacenados en la ubicación predeterminada y cambiar las rutas de acceso de los datos sensibles para usar el almacenamiento CE. Los fabricantes de dispositivos que usen esta opción deben inspeccionar cuidadosamente los datos que almacenan para asegurarse de que no contengan información personal.

Cuando se ejecuta en este modo, las siguientes APIs del sistema están disponibles para administrar de forma explícita un contexto respaldado por el almacenamiento de CE cuando sea necesario, que son equivalentes a sus contrapartes protegidas por el dispositivo.

  • Context.createCredentialProtectedStorageContext()
  • Context.isCredentialProtectedStorage()

Admite varios usuarios

Cada usuario en un entorno multiusuario obtiene una clave de encriptación independiente. Cada usuario obtiene dos claves: una DE y una CE. El usuario 0 debe acceder primero al dispositivo, ya que es un usuario especial. Esto es pertinente para los usos de la administración de dispositivos.

Las apps que reconocen la criptografía interactúan entre los usuarios de la siguiente manera: INTERACT_ACROSS_USERS y INTERACT_ACROSS_USERS_FULL permiten que una app actúe en todos los usuarios del dispositivo. Sin embargo, esas apps solo pueden acceder a los directorios con encriptación CE de los usuarios que ya están desbloqueados.

Es posible que una app pueda interactuar libremente en las áreas de DE, pero que un usuario esté desbloqueado no significa que todos los usuarios del dispositivo lo estén. La app debe verificar este estado antes de intentar acceder a estas áreas.

Cada ID de usuario del perfil de trabajo también obtiene dos claves: DE y CE. Cuando se cumple el desafío de trabajo, se desbloquea el usuario del perfil y KeyMint (en TEE) puede proporcionar la clave de TEE del perfil.

Cómo controlar las actualizaciones

La partición de recuperación no puede acceder al almacenamiento protegido por DE en la partición de datos del usuario. Se recomienda que los dispositivos que implementan FBE admitan OTA con actualizaciones del sistema A/B. Como la OTA se puede aplicar durante el funcionamiento normal, no es necesario realizar una recuperación para acceder a los datos de la unidad encriptada.

Cuando se usa una solución de OTA heredada, que requiere recuperación para acceder al archivo de OTA en la partición userdata, se debe tener en cuenta lo siguiente:

  1. Crea un directorio de nivel superior (por ejemplo, misc_ne) en la partición userdata.
  2. Configura este directorio de nivel superior para que no esté encriptado (consulta Excluye directorios).
  3. Crea un directorio dentro del directorio de nivel superior para almacenar los paquetes de OTA.
  4. Agrega una regla de SELinux y contextos de archivo para controlar el acceso a este directorio y su contenido. Solo el proceso o las apps que reciben actualizaciones OTA deberían poder leer y escribir en este directorio. Ninguna otra app ni proceso debería tener acceso a este directorio.

Validación

Para asegurarte de que la versión implementada de la función funcione según lo previsto, primero ejecuta las numerosas pruebas de encriptación de CTS, como DirectBootHostTest y EncryptionTest.

Si el dispositivo ejecuta Android 11 o una versión posterior, también ejecuta vts_kernel_encryption_test:

atest vts_kernel_encryption_test

o:

vts-tradefed run vts -m vts_kernel_encryption_test

Además, los fabricantes de dispositivos pueden realizar las siguientes pruebas manuales. En un dispositivo con la FBE habilitada, sucede lo siguiente:

  • Verifica que exista ro.crypto.state
    • Asegúrate de que ro.crypto.state esté encriptado
  • Verifica que exista ro.crypto.type
    • Asegúrate de que ro.crypto.type esté configurado como file.

Además, los verificadores pueden comprobar que el almacenamiento de CE esté bloqueado antes de que el dispositivo se haya desbloqueado por primera vez desde el inicio. Para ello, usa una compilación userdebug o eng, establece un PIN, un patrón o una contraseña en el usuario principal y reinicia el dispositivo. Antes de desbloquear el dispositivo, ejecuta el siguiente comando para verificar el almacenamiento de CE del usuario principal. Si el dispositivo usa el modo de usuario del sistema sin interfaz gráfica (la mayoría de los dispositivos Automotive), el usuario principal es el usuario 10, por lo que debes ejecutar lo siguiente:

adb root; adb shell ls /data/user/10

En otros dispositivos (la mayoría de los que no son Automotive), el usuario principal es el usuario 0, por lo que debes ejecutar lo siguiente:

adb root; adb shell ls /data/user/0

Verifica que los nombres de archivo que aparecen estén codificados en Base64, lo que indica que están encriptados y que la clave para desencriptarlos aún no está disponible. Si los nombres de archivo aparecen en texto sin formato, algo está mal.

También se recomienda que los fabricantes de dispositivos exploren la ejecución de las pruebas de Linux upstream para fscrypt en sus dispositivos o kernels. Estas pruebas forman parte del paquete de pruebas del sistema de archivos xfstests. Sin embargo, Android no admite oficialmente estas pruebas upstream.

Detalles de la implementación del AOSP

En esta sección, se proporcionan detalles sobre la implementación del AOSP y se describe cómo funciona la encriptación basada en archivos. No debería ser necesario que los fabricantes de dispositivos realicen cambios aquí para usar la FBE y el inicio directo en sus dispositivos.

Encriptación de fscrypt

La implementación del AOSP usa la encriptación "fscrypt" (compatible con ext4 y f2fs) en el kernel y, por lo general, se configura para lo siguiente:

  • Encripta el contenido de los archivos con AES-256 en modo XTS
  • Encripta los nombres de los archivos con AES-256 en el modo CBC-CTS

También se admite la encriptación de Adiantum. Cuando se habilita la encriptación de Adiantum, tanto el contenido como los nombres de los archivos se encriptan con Adiantum.

fscrypt admite dos versiones de políticas de encriptación: la versión 1 y la versión 2. La versión 1 dejó de estar disponible, y los requisitos del CDD para los dispositivos que se lanzan con Android 11 y versiones posteriores solo son compatibles con la versión 2. Las políticas de encriptación de la versión 2 usan HKDF-SHA512 para derivar las claves de encriptación reales de las claves proporcionadas por el espacio de usuario.

Para obtener más información sobre fscrypt, consulta la documentación del kernel upstream.

Clases de almacenamiento

En la siguiente tabla, se enumeran las claves de FBE y los directorios que protegen con más detalle:

Clase de almacenamiento Descripción Directorios
Sin encriptación Son directorios en /data que no pueden o no necesitan estar protegidos por la FBE. En los dispositivos que usan la encriptación de metadatos, estos directorios no están realmente sin encriptar, sino que están protegidos por la clave de encriptación de metadatos, que equivale a DE del sistema.
  • /data/apex, excepto /data/apex/decompressed y /data/apex/ota_reserved, que son DE del sistema
  • /data/lost+found
  • /data/preloads
  • /data/unencrypted
  • Todos los directorios cuyos subdirectorios usan diferentes claves de FBE Por ejemplo, como cada directorio /data/user/${user_id} usa una clave por usuario, /data/user no usa ninguna clave en sí.
DE del sistema Datos encriptados en el dispositivo que no están vinculados a un usuario en particular
  • /data/apex/decompressed
  • /data/apex/ota_reserved
  • /data/app
  • /data/misc
  • /data/system
  • /data/vendor
  • Todos los demás subdirectorios de /data que esta tabla no menciona como que tienen una clase diferente
Por inicio Archivos de sistema efímeros que no necesitan sobrevivir a un reinicio /data/per_boot
CE del usuario (interno) Datos encriptados con credenciales por usuario en el almacenamiento interno
  • /data/data (alias de /data/user/0)
  • /data/media/${user_id}
  • /data/misc_ce/${user_id}
  • /data/system_ce/${user_id}
  • /data/user/${user_id}
  • /data/vendor_ce/${user_id}
Usuario DE (interno) Datos encriptados por dispositivo por usuario en el almacenamiento interno
  • /data/misc_de/${user_id}
  • /data/system_de/${user_id}
  • /data/user_de/${user_id}
  • /data/vendor_de/${user_id}
Conversiones avanzadas de usuarios (adoptables) Datos encriptados con credenciales por usuario en el almacenamiento adoptable
  • /mnt/expand/${volume_uuid}/media/${user_id}
  • /mnt/expand/${volume_uuid}/misc_ce/${user_id}
  • /mnt/expand/${volume_uuid}/user/${user_id}
DE del usuario (adoptable) Datos encriptados por dispositivo por usuario en el almacenamiento adoptable
  • /mnt/expand/${volume_uuid}/misc_de/${user_id}
  • /mnt/expand/${volume_uuid}/user_de/${user_id}

Almacenamiento y protección de claves

Todas las claves de FBE se administran con vold y se almacenan encriptadas en el disco, excepto la clave por inicio, que no se almacena. En la siguiente tabla, se enumeran las ubicaciones en las que se almacenan las distintas claves de FBE:

Tipo de clave Ubicación de la clave Clase de almacenamiento de la ubicación de la clave
Clave de DE del sistema /data/unencrypted Sin encriptación
Claves de CE del usuario (internas) /data/misc/vold/user_keys/ce/${user_id} DE del sistema
Claves de DE del usuario (internas) /data/misc/vold/user_keys/de/${user_id} DE del sistema
Claves de CE del usuario (adoptables) /data/misc_ce/${user_id}/vold/volume_keys/${volume_uuid} CE del usuario (interno)
Claves DE (adoptables) del usuario /data/misc_de/${user_id}/vold/volume_keys/${volume_uuid} Usuario DE (interno)

Como se muestra en la tabla anterior, la mayoría de las claves de FBE se almacenan en directorios que están encriptados con otra clave de FBE. Las claves no se pueden desbloquear hasta que se haya desbloqueado la clase de almacenamiento que las contiene.

vold también aplica una capa de encriptación a todas las claves de FBE. Cada clave, además de las claves de CE para el almacenamiento interno, se encripta con AES-256-GCM usando su propia clave de Keystore que no se expone fuera del TEE. Esto garantiza que las claves de FBE no se puedan desbloquear, a menos que se haya iniciado un sistema operativo de confianza, según lo que se aplica en el inicio verificado. También se solicita la resistencia a la reversión en la clave del almacén de claves, lo que permite que las claves de FBE se borren de forma segura en los dispositivos en los que KeyMint admite la resistencia a la reversión. Como un resguardo de mejor esfuerzo para cuando la resistencia a la reversión no está disponible, el hash SHA-512 de 16,384 bytes aleatorios almacenados en el archivo secdiscardable almacenado junto con la clave se usa como el Tag::APPLICATION_ID de la clave de Keystore. Todos estos bytes se deben recuperar para recuperar una clave de FBE.

Las claves de CE para el almacenamiento interno reciben un nivel de protección más sólido que garantiza que no se puedan desbloquear sin conocer el factor de conocimiento de la pantalla de bloqueo (LSKF) del usuario (PIN, patrón o contraseña), un token de restablecimiento seguro de la contraseña o las claves del cliente y del servidor para una operación de reanudación tras el reinicio. Los tokens de restablecimiento de contraseña solo se pueden crear para perfiles de trabajo y dispositivos completamente administrados.

Para lograrlo, vold encripta cada clave de CE para el almacenamiento interno con una clave AES-256-GCM derivada de la contraseña sintética del usuario. La contraseña sintética es un secreto criptográfico inmutable de alta entropía que se genera de forma aleatoria para cada usuario. LockSettingsService en system_server administra la contraseña sintética y las formas en que se protege.

Para proteger la contraseña sintética con el LSKF, LockSettingsService primero extiende el LSKF pasándolo por scrypt, con un tiempo de alrededor de 25 ms y un uso de memoria de alrededor de 2 MiB. Como las LSKF suelen ser cortas, este paso no suele proporcionar mucha seguridad. La capa principal de seguridad es el elemento seguro (SE) o la limitación de frecuencia aplicada por TEE que se describe a continuación.

Si el dispositivo implementa la HAL de Weaver, LockSettingsService asigna el LSKF extendido a un secreto aleatorio de alta entropía almacenado en el SE o el TEE con Weaver. Luego, LockSettingsService encripta la contraseña sintética dos veces: primero, con una clave de software derivada del LSKF extendido y el secreto de Weaver, y, segundo, con una clave de Keystore no vinculada a la autenticación. Esto proporciona un límite de frecuencia aplicado por SE o TEE para las suposiciones de LSKF.

Si el dispositivo no implementa Weaver, LockSettingsService usa el LSKF extendido como contraseña de Gatekeeper. Luego, LockSettingsService encripta la contraseña sintética dos veces: primero, con una clave de software derivada del LSKF extendido y el hash de un archivo secdiscardable y, segundo, con una clave de Keystore que está vinculada a la autenticación de la inscripción de Gatekeeper. Esto proporciona un límite de frecuencia de intentos de adivinar la LSKF que se aplica en el TEE.

Cuando se cambia el LSKF, LockSettingsService borra toda la información asociada con la vinculación de la contraseña sintética al LSKF anterior. En los dispositivos que admiten Weaver o claves de Keystore resistentes a la reversión, esto garantiza la eliminación segura de la vinculación anterior. Por este motivo, las protecciones que se describen aquí se aplican incluso cuando el usuario no tiene un LSKF.