Cifrado basado en archivos

Android 7.0 y versiones posteriores admiten el cifrado basado en archivos (FBE). El cifrado basado en archivos permite cifrar diferentes archivos con diferentes claves que se pueden desbloquear de forma independiente.

Este artículo describe cómo habilitar el cifrado basado en archivos en nuevos dispositivos y cómo las aplicaciones del sistema pueden usar las API de arranque directo para ofrecer a los usuarios la mejor y más segura experiencia posible.

Arranque directo

El cifrado basado en archivos habilita una nueva característica introducida en Android 7.0 llamada Arranque directo . Direct Boot permite que los dispositivos encriptados arranquen directamente en la pantalla de bloqueo. Anteriormente, en dispositivos encriptados que usaban encriptación de disco completo (FDE), los usuarios debían proporcionar credenciales antes de poder 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, pero estaban limitados a operaciones básicas de marcación de emergencia.

Con la introducción del cifrado basado en archivos (FBE) y las nuevas API para que las aplicaciones reconozcan el cifrado, es posible que estas aplicaciones operen dentro de un contexto limitado. Esto puede ocurrir antes de que los usuarios hayan proporcionado sus credenciales mientras se sigue protegiendo la información privada del usuario.

En un dispositivo habilitado para FBE, cada usuario del dispositivo tiene dos ubicaciones de almacenamiento disponibles para las aplicaciones:

  • Almacenamiento de Credential Encrypted (CE), que es la ubicación de almacenamiento predeterminada y solo está disponible después de que el usuario haya desbloqueado el dispositivo.
  • Almacenamiento de dispositivo cifrado (DE), que es una ubicación de almacenamiento disponible tanto durante el modo de arranque directo como después de que el usuario haya desbloqueado el dispositivo.

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

La API de arranque directo permite que las aplicaciones con reconocimiento de cifrado accedan a cada una de estas áreas. Hay cambios en el ciclo de vida de la aplicación para adaptarse a la necesidad de notificar a las aplicaciones cuando el almacenamiento de CE de un usuario está desbloqueado en respuesta al primer ingreso de credenciales en la pantalla de bloqueo, o en el caso de un perfil de trabajo que presenta un desafío laboral . Los dispositivos que ejecutan Android 7.0 deben ser compatibles con estas nuevas API y ciclos de vida, independientemente de si implementan o no FBE. Aunque, sin FBE, el almacenamiento DE y CE siempre estará en estado desbloqueado.

Se proporciona una implementación completa de cifrado basado en archivos en los sistemas de archivos Ext4 y F2FS en el Proyecto de código abierto de Android (AOSP) y solo debe habilitarse en dispositivos que cumplan con los requisitos. Es posible que los fabricantes que opten por usar FBE deseen explorar formas de optimizar la función en función del sistema en chip (SoC) utilizado.

Todos los paquetes necesarios en AOSP se han actualizado para reconocer el arranque directo. Sin embargo, cuando los fabricantes de dispositivos utilicen versiones personalizadas de estas aplicaciones, querrán asegurarse de que, como mínimo, haya paquetes compatibles con el arranque directo que brinden 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 cifrado basado en archivos, en la que vold ( system/vold ) proporciona la funcionalidad para administrar dispositivos y volúmenes de almacenamiento en Android. La adición de FBE proporciona a vold varios comandos nuevos para admitir la administración de claves para las claves CE y DE de múltiples usuarios. Además de los cambios principales para usar las capacidades de cifrado basadas en archivos en el kernel, muchos paquetes del sistema, incluidos LockScreen y SystemUI, se han modificado para admitir las funciones FBE y Direct Boot. Éstas incluyen:

  • Marcador AOSP (paquetes/aplicaciones/Marcador)
  • Reloj de escritorio (paquetes/aplicaciones/DeskClock)
  • LatinIME (paquetes/métodos de entrada/LatinIME)*
  • Aplicación de configuración (paquetes/aplicaciones/Configuración)*
  • SystemUI (marcos/base/paquetes/SystemUI)*

* Aplicaciones del sistema que usan el atributo de manifiesto defaultToDeviceProtectedStorage

Se pueden encontrar más ejemplos de aplicaciones y servicios que son compatibles con el cifrado ejecutando el comando mangrep directBootAware en el directorio de marcos o paquetes del árbol fuente de AOSP.

dependencias

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

  • Soporte de kernel para cifrado Ext4 o cifrado F2FS.
  • Keymaster Support con HAL versión 1.0 o 2.0. No hay soporte para Keymaster 0.3 ya que no proporciona las capacidades necesarias ni asegura una protección suficiente para las claves de cifrado.
  • Keymaster/ Keystore y Gatekeeper deben implementarse en un entorno de ejecución de confianza (TEE) para brindar protección a las claves DE de modo que un sistema operativo no autorizado (sistema operativo personalizado instalado en el dispositivo) no pueda simplemente solicitar las claves DE.
  • Se requiere raíz de confianza de hardware y arranque verificado vinculado a la inicialización del maestro de claves para garantizar que un sistema operativo no autorizado no pueda acceder a las credenciales de Device Encryption.

Nota : las políticas de almacenamiento se aplican a una carpeta y todas sus subcarpetas. Los fabricantes deben limitar los contenidos que no están cifrados a la carpeta OTA y la carpeta que contiene la clave que descifra el sistema. La mayoría de los contenidos deben residir en un almacenamiento con credenciales encriptadas en lugar de un almacenamiento con dispositivos encriptados.

Implementación

En primer lugar, las aplicaciones como los relojes de alarma, el teléfono y las funciones de accesibilidad deben hacerse android:directBootAware de acuerdo con la documentación del desarrollador de Direct Boot .

Soporte del núcleo

El soporte de kernel para el cifrado Ext4 y F2FS está disponible en los kernels comunes de Android, versión 3.18 y superior. Para habilitarlo en un kernel que es la versión 5.1 o superior, utilice:

CONFIG_FS_ENCRYPTION=y

Para kernels más antiguos, use CONFIG_EXT4_ENCRYPTION=y si el sistema de archivos de datos de userdata de su dispositivo es Ext4, o use CONFIG_F2FS_FS_ENCRYPTION=y si el sistema de archivos de datos de userdata de su dispositivo es F2FS.

Si su dispositivo admitirá el almacenamiento adoptable o utilizará el cifrado de metadatos en el almacenamiento interno, habilite también las opciones de configuración del kernel necesarias para el cifrado de metadatos como se describe en la documentación de cifrado de metadatos .

Además del soporte funcional para el cifrado Ext4 o F2FS, los fabricantes de dispositivos también deberían habilitar la aceleración criptográfica para acelerar el cifrado basado en archivos y mejorar la experiencia del usuario. Por ejemplo, en dispositivos basados ​​en ARM64, la aceleración ARMv8 CE (Cryptography Extensions) 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 hardware de cifrado en línea , que cifra/descifra los datos mientras se encuentran en el camino hacia/desde el dispositivo de almacenamiento. Los núcleos comunes de Android (versión 4.14 y superior) contienen un marco que permite el uso de cifrado en línea cuando el hardware y el soporte del controlador del proveedor están disponibles. El marco de cifrado en línea 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 su dispositivo usa almacenamiento basado en UFS, habilite también:

CONFIG_SCSI_UFS_CRYPTO=y

Si su dispositivo usa almacenamiento basado en eMMC, habilite también:

CONFIG_MMC_CRYPTO=y

Habilitación del cifrado basado en archivos

Habilitar FBE en un dispositivo requiere habilitarlo en el almacenamiento interno (datos de userdata ). Esto también habilita automáticamente FBE en almacenamiento adoptable; sin embargo, el formato de cifrado en el almacenamiento adoptable puede anularse si es necesario.

Almacenamiento interno

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 cifrado 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 utiliza para cifrar el contenido del archivo. Puede ser aes-256-xts o adiantum . Desde Android 11 también se puede dejar en blanco para especificar el algoritmo predeterminado, que es aes-256-xts .
  • El parámetro filenames_encryption_mode define qué algoritmo criptográfico se utiliza para cifrar los nombres de los archivos. Puede ser aes-256-cts , aes-256-heh o adiantum . 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 de flags , nuevo en Android 11, es una lista de banderas separadas por el carácter + . Se admiten las siguientes banderas:
    • El indicador v1 selecciona las políticas de cifrado de la versión 1; el indicador v2 selecciona las políticas de cifrado de la versión 2. Las políticas de cifrado de la versión 2 utilizan una función de derivación de claves más segura y flexible. El valor predeterminado es v2 si el dispositivo se lanzó en Android 11 o superior (según lo determinado por ro.product.first_api_level ), o v1 si el dispositivo se lanzó en Android 10 o inferior.
    • El indicador inlinecrypt_optimized selecciona un formato de cifrado que está optimizado para hardware de cifrado en línea que no maneja grandes cantidades de claves de manera eficiente. Lo hace derivando solo una clave de cifrado de contenido de archivo por clave CE o DE, en lugar de una por archivo. La generación de IV (vectores de inicialización) se ajusta en consecuencia.
    • El indicador 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. Este indicador solo debe usarse en hardware de cifrado en línea que cumpla con la especificación JEDEC eMMC v5.2 y, por lo tanto, solo admita IV de 32 bits. En otro hardware de cifrado en línea, use inlinecrypt_optimized en su lugar. Esta marca nunca debe usarse en almacenamiento basado en UFS; la especificación UFS permite el uso de IV de 64 bits.
    • En los dispositivos que admiten claves encapsuladas en hardware , la wrappedkey_v0 permite el uso de claves encapsuladas en hardware para FBE. Esto solo se puede usar en combinación con la opción de montaje inlinecrypt y el inlinecrypt_optimized o emmc_optimized .

Si no utiliza hardware de cifrado en línea, la configuración recomendada para la mayoría de los dispositivos es fileencryption=aes-256-xts . Si utiliza hardware de cifrado en línea, la configuración recomendada para la mayoría de los dispositivos es fileencryption=aes-256-xts:aes-256-cts:inlinecrypt_optimized (o equivalente fileencryption=::inlinecrypt_optimized ). En dispositivos sin ningún tipo de aceleración AES, se puede usar Adiantum en lugar de AES configurando fileencryption=adiantum .

En dispositivos que se lanzaron con Android 10 o anterior, también se acepta fileencryption=ice para especificar el uso del modo de cifrado de contenido de archivo FSCRYPT_MODE_PRIVATE . Los núcleos comunes de Android no implementan este modo, pero los proveedores pueden implementarlo mediante parches de núcleo personalizados. El formato en disco producido por este modo era específico del proveedor. En los dispositivos que se inician con Android 11 o superior, este modo ya no está permitido y se debe usar un formato de cifrado estándar en su lugar.

De forma predeterminada, el cifrado del contenido de los archivos se realiza mediante la API de criptografía del kernel de Linux. Si desea utilizar hardware de cifrado en línea, agregue también la inlinecrypt montaje de cifrado en línea. Por ejemplo, una línea fstab completa podría verse así:

/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, FBE y el almacenamiento adoptable se pueden usar juntos.

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

En dispositivos que se lanzaron con Android 11 o superior, use las siguientes propiedades:

  • ro.crypto.volume.options (nuevo en Android 11) selecciona el formato de cifrado FBE en el almacenamiento adoptable. Tiene la misma sintaxis que el argumento de la opción fstab de fileencryption de archivos y utiliza los mismos valores predeterminados. Consulte las recomendaciones para el fileencryption de archivos anteriores para saber qué usar aquí.
  • ro.crypto.volume.metadata.encryption selecciona el formato de cifrado de metadatos en el almacenamiento adoptable. Consulte la documentación de cifrado de metadatos .

En dispositivos que se lanzaron con Android 10 o inferior, use las siguientes propiedades:

  • ro.crypto.volume.contents_mode selecciona el modo de cifrado de contenido. Esto es equivalente al primer campo separado por dos puntos de ro.crypto.volume.options .
  • ro.crypto.volume.filenames_mode selecciona el modo de cifrado de nombres de archivo. Esto es equivalente al segundo campo separado por dos puntos de ro.crypto.volume.options , excepto que el valor predeterminado en los dispositivos que se iniciaron con Android 10 o inferior es aes-256-heh . En la mayoría de los dispositivos, esto debe anularse explícitamente a aes-256-cts .
  • ro.crypto.fde_algorithm y ro.crypto.fde_sector_size seleccionan el formato de cifrado de metadatos en el almacenamiento adoptable. Consulte la documentación de cifrado de metadatos .

Integración con Keymaster

La generación de claves y la gestión del conjunto de claves del núcleo están a cargo de vold . La implementación AOSP de FBE requiere que el dispositivo admita Keymaster HAL versión 1.0 o posterior. No hay soporte para versiones anteriores de Keymaster HAL.

En el primer arranque, las claves del usuario 0 se generan e instalan al principio del proceso de arranque. En el momento en que finaliza la fase on-post-fs de init , Keymaster debe estar listo para manejar las solicitudes. En los dispositivos Pixel, esto se maneja con un bloque de script que garantiza que Keymaster se inicie antes de que se monte /data .

Política de cifrado

El cifrado basado en archivos aplica la política de cifrado a nivel de directorio. Cuando se crea por primera vez la partición de datos de userdata de un dispositivo, los scripts de init aplican las estructuras y políticas básicas. Estos scripts activarán la creación de las claves CE y DE del primer usuario (usuario 0) y definirán qué directorios se cifrarán con estas claves. Cuando se crean usuarios y perfiles adicionales, las claves adicionales necesarias se generan y almacenan en el almacén de claves; se crean sus ubicaciones de almacenamiento de credenciales y dispositivos y la política de cifrado vincula estas claves a esos directorios.

En Android 11 y versiones posteriores, la política de cifrado ya no está codificada en una ubicación centralizada, sino que se define mediante argumentos para los comandos mkdir en los scripts de inicio. Los directorios encriptados con la clave DE del sistema usan encryption=Require , mientras que los directorios no encriptados (o directorios cuyos subdirectorios están encriptados con claves por usuario) usan encryption=None .

En Android 10, la política de cifrado estaba codificada en esta ubicación:

/system/extras/libfscrypt/fscrypt_init_extensions.cpp

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

/system/extras/ext4_utils/ext4_crypt_init_extensions.cpp

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

El único caso de uso aceptable conocido para esto es en apoyo de las capacidades OTA heredadas.

Compatibilidad con arranque directo en aplicaciones del sistema

Hacer que las aplicaciones sean conscientes del arranque directo

Para facilitar la migración rápida de las aplicaciones del sistema, hay dos nuevos atributos que se pueden configurar en el nivel de la aplicación. El atributo defaultToDeviceProtectedStorage solo está disponible para las aplicaciones del sistema. El atributo directBootAware está disponible para todos.

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

El atributo directBootAware en el nivel de la aplicación es una forma abreviada de marcar todos los componentes de la aplicación como compatibles con el cifrado.

El atributo defaultToDeviceProtectedStorage redirige la ubicación de almacenamiento de la aplicación predeterminada para que apunte al almacenamiento DE en lugar de apuntar al almacenamiento CE. Las aplicaciones del sistema que usan este indicador deben auditar cuidadosamente todos los datos almacenados en la ubicación predeterminada y cambiar las rutas de los datos confidenciales para usar el almacenamiento CE. Los fabricantes de dispositivos que usan esta opción deben inspeccionar cuidadosamente los datos que están almacenando para asegurarse de que no contengan información personal.

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

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

Soporte para múltiples usuarios

Cada usuario en un entorno multiusuario obtiene una clave de cifrado separada. Cada usuario obtiene dos claves: una clave DE y una clave CE. El usuario 0 debe iniciar sesión en el dispositivo primero, ya que es un usuario especial. Esto es pertinente para los usos de administración de dispositivos .

Las aplicaciones con reconocimiento de cifrado interactúan entre los usuarios de esta manera: INTERACT_ACROSS_USERS e INTERACT_ACROSS_USERS_FULL permiten que una aplicación actúe entre todos los usuarios del dispositivo. Sin embargo, esas aplicaciones solo podrán acceder a directorios cifrados con CE para usuarios que ya están desbloqueados.

Una aplicación puede interactuar libremente en las áreas de DE, pero un usuario desbloqueado no significa que todos los usuarios del dispositivo estén desbloqueados. La aplicación debería comprobar 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 laboral, el usuario del perfil se desbloquea y Keymaster (en TEE) puede proporcionar la clave TEE del perfil.

Manejo de actualizaciones

La partición de recuperación no puede acceder al almacenamiento protegido por DE en la partición de datos de usuario. Se recomienda encarecidamente que los dispositivos que implementan FBE admitan OTA mediante 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 en la unidad cifrada.

Al usar una solución OTA heredada, que requiere recuperación para acceder al archivo OTA en la partición de datos de userdata :

  1. Cree un directorio de nivel superior (por ejemplo misc_ne ) en la partición de datos de userdata .
  2. Agregue este directorio de nivel superior a la excepción de la política de cifrado (consulte la política de cifrado anterior).
  3. Cree un directorio dentro del directorio de nivel superior para almacenar paquetes OTA.
  4. Agregue una regla de SELinux y contextos de archivo para controlar el acceso a esta carpeta y su contenido. Solo el proceso o las aplicaciones que reciben actualizaciones OTA deben poder leer y escribir en esta carpeta. Ninguna otra aplicación o proceso debería tener acceso a esta carpeta.

Validación

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

Si el dispositivo ejecuta Android 11 o superior, también ejecute 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 FBE habilitado:

  • Compruebe que existe ro.crypto.state
    • Asegúrese de que ro.crypto.state esté encriptado
  • Compruebe que existe ro.crypto.type
    • Asegúrese de que ro.crypto.type esté configurado en file

Además, los evaluadores pueden iniciar una instancia de userdebug de usuario con una pantalla de bloqueo configurada en el usuario principal. Luego adb shell en el dispositivo y use su para convertirse en root. Asegúrese de que /data/data contenga nombres de archivos cifrados; si no es así, algo anda mal.

También se alienta a los fabricantes de dispositivos a explorar la ejecución de las pruebas de Linux upstream para fscrypt en sus dispositivos o kernels. Estas pruebas son parte del conjunto de pruebas del sistema de archivos xfstests. Sin embargo, estas pruebas ascendentes no son oficialmente compatibles con Android.

Detalles de implementación de AOSP

Esta sección proporciona detalles sobre la implementación de AOSP y describe cómo funciona el cifrado basado en archivos. No debería ser necesario que los fabricantes de dispositivos realicen ningún cambio aquí para usar FBE y Direct Boot en sus dispositivos.

cifrado fscrypt

La implementación de AOSP utiliza el cifrado "fscrypt" (compatible con ext4 y f2fs) en el núcleo y normalmente está configurado para:

  • Cifre el contenido del archivo con AES-256 en modo XTS
  • Cifrar nombres de archivos con AES-256 en modo CBC-CTS

El cifrado Adiantum también es compatible. Cuando el cifrado de Adiantum está habilitado, tanto el contenido como los nombres de los archivos se cifran con Adiantum.

Para obtener más información sobre fscrypt, consulte la documentación del núcleo original.

Derivación de claves

Las claves de cifrado basadas en archivos, que son claves de 512 bits, se almacenan cifradas por otra clave (una clave AES-GCM de 256 bits) que se encuentra en el TEE. Para utilizar esta llave TEE se deben cumplir tres requisitos:

  • El token de autenticación
  • La credencial estirada
  • El "hash descartable sec"

El token de autenticación es un token autenticado criptográficamente generado por Gatekeeper cuando un usuario inicia sesión correctamente. El TEE se negará a utilizar la clave a menos que se proporcione el token de autenticación correcto. Si el usuario no tiene credenciales, no se usa ni se necesita ningún token de autenticación.

La credencial extendida es la credencial de usuario después de salar y estirar con el algoritmo scrypt . En realidad, la credencial se codifica una vez en el servicio de configuración de bloqueo antes de pasar a vold para pasar a scrypt . Este está vinculado criptográficamente a la clave en el TEE con todas las garantías que se aplican a KM_TAG_APPLICATION_ID . Si el usuario no tiene una credencial, entonces no se usa ni se necesita una credencial ampliada.

El secdiscardable hash es un hash de 512 bits de un archivo aleatorio de 16 KB almacenado junto con otra información utilizada para reconstruir la clave, como la semilla. Este archivo se elimina de forma segura cuando se elimina la clave, o se cifra de una forma nueva; esta protección adicional garantiza que un atacante deba recuperar cada bit de este archivo eliminado de forma segura para recuperar la clave. Este está vinculado criptográficamente a la clave en el TEE con todas las garantías que se aplican a KM_TAG_APPLICATION_ID .

En la mayoría de los casos, las claves FBE también se someten a un paso adicional de derivación de claves en el kernel para generar las subclaves que se usan realmente para realizar el cifrado, por ejemplo, claves por archivo o por modo. Para las políticas de cifrado de la versión 2, se usa HKDF-SHA512 para esto.