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 Direct Boot para ofrecer a los usuarios la mejor experiencia posible y más segura.

Todos los dispositivos que se lancen 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 conozcan la encriptación, es posible que estas apps operen en un contexto limitado. Esto puede suceder 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 arranque.

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 el 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 se debe habilitar en los dispositivos que cumplen con los requisitos. Los fabricantes que decidan usar 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
  • 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 FBE proporciona a vold varios comandos nuevos para admitir la administración de claves para 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, incluidos la pantalla de bloqueo y SystemUI, para admitir las funciones de FBE y de inicio directo. Por ejemplo:

  • Marcador del 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

Puedes encontrar más ejemplos de apps y servicios que admiten el cifrado ejecutando el comando mangrep directBootAware en el directorio de frameworks o paquetes del árbol de origen de 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 deben implementarse en un entorno de ejecución confiable (TEE) para brindar protección a las claves de DE, de modo que un SO no autorizado (SO personalizado instalado en el dispositivo) no pueda 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 el cifrado Ext4 y F2FS está disponible en los kernels comunes de Android, versión 3.18 y posteriores. Para habilitarlo en un kernel 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 adaptable o usa la encriptación de metadatos en el almacenamiento interno, también debes habilitar las opciones de configuración del kernel necesarias para la encriptación de metadatos, como se describe en la documentación sobre la 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 dispositivos basados en ARM64, se puede habilitar la aceleración de ARMv8 CE (extensiones de criptografía) configurando las siguientes opciones 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. Para habilitar el framework de encriptación intercalada, establece 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 el FBE en un dispositivo, debes habilitarlo en el almacenamiento interno (userdata). Esto también habilita automáticamente el FBE en el almacenamiento externo adoptable. Sin embargo, el formato de encriptación en el almacenamiento externo 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, mientras que 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 se debe usar 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, ya que 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 que el tamaño de la unidad de datos de encriptación 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 de los archivos. 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 fileencryption=::inlinecrypt_optimized de forma equivalente). En los dispositivos sin ninguna forma 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 archivos 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 admite AES-HCTR2, puedes habilitarlo para la encriptación de nombres de archivos configurando 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 disco que producía este modo era específico del proveedor. En los dispositivos que se lanzan con Android 11 o versiones posteriores, este modo ya no está permitido 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, se pueden usar el FBE y el almacenamiento adaptable en conjunto.

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 de 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 adaptable. 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 de 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 nombres de archivos. 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

El HAL de KeyMint debe iniciarse como parte de la clase early_hal. Esto se debe a que FBE requiere que KeyMint esté listo para controlar las solicitudes en la fase de inicio de 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 recursiva y no se pueden anular en los subdirectorios.

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 inicialización. Los valores posibles de <action> se documentan en el README del lenguaje de inicialización de Android.

En Android 10, las acciones de encriptación de init se codificaron de forma rígida 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.

Compatibilidad con el inicio directo en las apps del sistema

Cómo hacer que las apps sean compatibles con el inicio directo

Para facilitar la migración rápida de las apps del sistema, hay dos atributos nuevos que se pueden configurar 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 de 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 administración de dispositivos.

Las apps que reconocen la encriptación interactúan con 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 encriptados con CE para los usuarios que ya están desbloqueados.

Es posible que una app pueda interactuar libremente en todas las áreas del DE, pero que un usuario desbloqueado no significa que todos los usuarios del dispositivo estén desbloqueados. 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 implementen FBE admitan las 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 OTA heredada, que requiere recuperación para acceder al archivo OTA en la partición userdata, haz 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 Cómo excluir 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 archivos para controlar el acceso a este directorio y su contenido. Solo el proceso o las apps que reciben actualizaciones OTA deben poder leer y escribir en este directorio. Ninguna otra app o proceso debe 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, haz lo siguiente:

  • Comprueba 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 se desbloquee el dispositivo 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 para automóviles), el usuario principal es el usuario 10, por lo que debes ejecutar el siguiente comando:

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 los archivos aparecen en texto sin formato, algo anda 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 del archivo 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 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 del 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 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 es equivalente a la DE del sistema.
  • /data/apex, sin incluir /data/apex/decompressed ni /data/apex/ota_reserved, que son DE del sistema
  • /data/lost+found
  • /data/preloads
  • /data/unencrypted
  • Son todos los directorios cuyos subdirectorios usan diferentes claves de FBE. Por ejemplo, dado que cada directorio /data/user/${user_id} usa una clave por usuario, /data/user no usa ninguna clave.
Sistema DE 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 del 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}
CE del usuario (adoptable) 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}
Usuario DE (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

vold administra todas las claves de FBE y las almacena encriptadas en el disco, excepto la clave por inicio, que no se almacena en absoluto. En la siguiente tabla, se indican 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} Sistema DE
Claves de CE del usuario (adoptables) /data/misc_ce/${user_id}/vold/volume_keys/${volume_uuid} CE del usuario (interno)
Claves DE del usuario (adoptables) /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 encriptados por otra clave de FBE. Las llaves no se pueden desbloquear hasta que se desbloquee 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 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 deben recuperarse 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. Dado que 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 el TEE que se describe a continuación.

Si el dispositivo implementa la HAL de Weaver, LockSettingsService asigna la LSKF extendida 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 una limitación de frecuencia de intentos de adivinar la LSKF aplicada por SE o TEE.

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 de la LSKF extendida y el hash de un archivo descartable, y segundo con una clave de Keystore que está vinculada por autenticación al registro de Gatekeeper. Esto proporciona un límite de frecuencia aplicado por el TEE para las suposiciones de LSKF.

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 una LSKF.