Encriptación de disco completo

La encriptación de disco completo es el proceso de codificación de todos los datos del usuario en un dispositivo Android a través de un clave encriptada. Una vez que se encripta un dispositivo, todos los datos creados por el usuario se encriptan automáticamente antes de confirmarlos en el disco, y todas las operaciones de lectura desencriptan automáticamente los datos antes de devolverlos al proceso de llamada.

La encriptación de disco completo se introdujo en Android en 4.4, pero Android 5.0 estas nuevas funciones:

  • Se creó la encriptación rápida, que solo encripta los bloques utilizados en la partición de datos. para evitar que el primer inicio tarde mucho tiempo. Solo los sistemas de archivos ext4 y f2fs admiten actualmente la encriptación rápida.
  • Se agregó la marca fstab forceencrypt para encriptar en el primer inicio.
  • Se agregó compatibilidad con patrones y encriptación sin contraseña.
  • Se agregó almacenamiento con copia de seguridad en hardware de la clave de encriptación mediante Trusted La capacidad de firma del entorno de ejecución (TEE) (por ejemplo, en una zona de confianza). Consulta Almacena la clave encriptada para obtener más información. más detalles.

Precaución: Los dispositivos se actualizaron a Android 5.0 y, luego, la encriptación puede devolverse al estado de no encriptado mediante el restablecimiento de la configuración de fábrica. Nuevo Android 5.0 los dispositivos encriptados en el primer inicio no pueden devolverse a un estado desencriptado.

Cómo funciona la encriptación de disco completo de Android

La encriptación de disco completo de Android se basa en dm-crypt, que es un kernel. que funciona en la capa del dispositivo de almacenamiento en bloques. Debido a esto, la encriptación funciona con MultiMediaCard incorporada (eMMC) y dispositivos Flash similares que se presentan al kernel como bloques dispositivos. La encriptación no es posible con YAFFS, que se comunica directamente con un chip de memoria flash NAND sin procesar.

El algoritmo de encriptación es el Estándar de encriptación avanzada (AES) de 128 bits con encadenamiento de bloques de cifrado (CBC) y ESSIV:SHA256. La clave maestra se encripta con AES de 128 bits a través de llamadas a la biblioteca de OpenSSL. Debes usar 128 bits o más para la clave (con 256 es opcional).

Nota: Los OEMs pueden usar 128 bits o más para encriptar la clave principal.

En la versión de Android 5.0, hay cuatro tipos de estados de encriptación:

  • default
  • PIN
  • contraseña
  • patrón

En el primer inicio, el dispositivo crea una clave maestra de 128 bits generada de forma aleatoria. y genera un hash con una contraseña predeterminada y la sal almacenada. La contraseña predeterminada es "default_password". Sin embargo, el hash resultante también se firma a través de un TEE (como TrustZone), que usa un hash de la firma para encriptar la clave maestra.

Puedes encontrar la contraseña predeterminada definida en el archivo cryptfs.cpp del proyecto de código abierto de Android.

Cuando el usuario establece el PIN, el pase o la contraseña en el dispositivo, solo se usará la clave de 128 bits se vuelve a encriptar y se almacena. (es decir, los cambios de PIN, contraseña o patrón del usuario NO provocan la nueva encriptación de los datos del usuario). Ten en cuenta que el dispositivo administrado puede estar sujeto a restricciones de PIN, patrón o contraseña.

init y vold administran la encriptación. init llama a vold, y vold establece propiedades para activar eventos en init. Otras partes del sistema también pueden observar las propiedades para realizar tareas como informar el estado, solicitar contraseña o solicitar que restablezca la configuración de fábrica en caso de un error fatal. Para invocar las funciones de encriptación en vold, el sistema usa los comandos cryptfs de la herramienta de línea de comandos vdc: checkpw, restart, enablecrypto, changepw, cryptocomplete, verifypw, setfield, getfield, mountdefaultencrypted, getpwtype, getpw y clearpw.

Para encriptar, desencriptar o limpiar /data, /data no debe estar montado. Sin embargo, para mostrar cualquier interfaz de usuario (IU), se debe iniciar el framework, que requiere que se ejecute /data. Para resolver este dilema, se activa un sistema de archivos temporal en /data. Esto permite que Android solicite contraseñas, muestre el progreso o sugiera una limpieza de datos según sea necesario. Sin embargo, impone la limitación de que, para cambiar del sistema de archivos temporal al sistema de archivos /data real, el sistema debe detener todos los procesos con archivos abiertos en el sistema de archivos temporal y reiniciarlos en el sistema de archivos /data real. Para ello, todos los servicios debe estar en uno de estos tres grupos: core, main y late_start

  • core: Nunca se debe apagar después de iniciar.
  • main: Apaga el dispositivo y, luego, reinícialo después de ingresar la contraseña del disco.
  • late_start: No se inicia hasta después de que se haya desencriptado y activado /data.

Para activar estas acciones, la propiedad vold.decrypt se establece en diversas cadenas. Para finalizar y reiniciar servicios, los comandos de init son los siguientes:

  • class_reset: Detiene un servicio, pero permite que se reinicie con class_start.
  • class_start: Reinicia un servicio.
  • class_stop: Detiene un servicio y agrega una marca SVC_DISABLED. Los servicios detenidos no responden a class_start.

Flujos

Existen cuatro flujos para un dispositivo encriptado. Un dispositivo se encripta solo una vez y, luego, sigue un flujo de inicio normal.

  • Encripta un dispositivo que no estaba encriptado:
    • Encriptar un dispositivo nuevo con forceencrypt: Encriptación obligatoria durante el primer inicio (a partir de Android L).
    • Encripta un dispositivo existente: Encriptación iniciada por el usuario (Android K y versiones anteriores).
  • Cómo iniciar un dispositivo encriptado:
    • Iniciar un dispositivo encriptado sin contraseña: Se inicia un dispositivo encriptado que No tiene una contraseña establecida (relevante para dispositivos con Android 5.0 y versiones posteriores).
    • Inicio de un dispositivo encriptado con una contraseña: Inicio de un dispositivo encriptado que tiene una contraseña establecida.

Además de estos flujos, es posible que el dispositivo no pueda encriptar /data. Cada uno de estos flujos se explica en detalle a continuación.

Encripta un dispositivo nuevo con forceencrypt

Este es el primer inicio normal para un dispositivo con Android 5.0.

  1. Cómo detectar un sistema de archivos no encriptado con la marca forceencrypt

    /data no está encriptado, pero debe estarlo porque forceencrypt lo exige. Desactivar /data.

  2. Comenzar a encriptar /data

    vold.decrypt = "trigger_encryption" activa init.rc, lo que hará que vold encripte /data sin contraseña. (No se estableció ninguno, ya que debería ser un dispositivo nuevo).

  3. Activa tmpfs

    vold activa un /data de tmpfs (mediante las opciones de tmpfs de ro.crypto.tmpfs_options) y establece la propiedad vold.encrypt_progress en 0. vold prepara el tmpfs /data para iniciar un sistema encriptado y establece la propiedad vold.decrypt en trigger_restart_min_framework.

  4. Cómo mostrar el framework para mostrar el progreso

    Debido a que el dispositivo prácticamente no tiene datos para encriptar, la barra de progreso no aparecerá con frecuencia porque la encriptación se realiza muy rápido. Consulta Cómo encriptar un dispositivo existente para obtener más detalles sobre la IU de progreso.

  5. Cuando /data esté encriptado, elimina el framework.

    vold establece vold.decrypt en trigger_default_encryption, que da inicio al servicio defaultcrypto. (Esto inicia el siguiente flujo para activar un datos del usuario encriptados de forma predeterminada). trigger_default_encryption verifica el tipo de encriptación para ver si /data está encriptado con o sin una contraseña. Como los dispositivos Android 5.0 se encriptan en el primer inicio, no debería haber ninguna contraseña establecida. Por lo tanto, desencriptamos y activamos /data.

  6. Montaje /data

    Luego, init activa /data en un RAMDisk de tmpfs con los parámetros que recopila de ro.crypto.tmpfs_options, que se estableció en init.rc.

  7. Framework de inicio

    vold establece vold.decrypt en trigger_restart_framework, que continúa el inicio habitual el proceso de administración de recursos.

Encripta un dispositivo existente

Esto es lo que sucede cuando encriptas un dispositivo Android K o anterior que no está encriptado y que se migró a L.

Este proceso lo inicia el usuario y se conoce como “encriptación interna” en el código. Cuando un usuario selecciona encriptar un dispositivo, la IU se asegura de que la batería esté completamente cargada y que el adaptador de CA esté conectado para que haya suficiente energía para finalizar el proceso de encriptación.

Advertencia: Si el dispositivo se queda sin batería y se apaga antes de terminar de encriptar los datos de los archivos, estos quedarán en un estado parcialmente encriptado. Se debe restablecer la configuración de fábrica del dispositivo y se perderán todos los datos.

Para habilitar la encriptación en el lugar, vold inicia un bucle para leer cada sector del dispositivo de bloques real y, luego, escribirlo en el dispositivo de bloques de criptografía. vold verifica si un sector está en uso antes de leerlo y escribirlo, lo que hace que la encriptación sea mucho más rápida en un dispositivo nuevo que tiene pocos datos o no tiene ninguno.

Estado del dispositivo: Establece ro.crypto.state = "unencrypted". y ejecuta el activador on nonencrypted init para continuar con el inicio.

  1. Cómo verificar la contraseña

    La IU llama a vold con el comando cryptfs enablecrypto inplace, en el que passwd es la contraseña de la pantalla de bloqueo del usuario.

  2. Elimina el framework

    vold verifica si hay errores, muestra -1 si no puede encriptar y imprime un motivo en el registro. Si puede encriptar, configura la propiedad vold.decrypt. a trigger_shutdown_framework. Esto hará que init.rc detener servicios en las clases late_start y main

  3. Crea un pie de página de criptografía
  4. Cómo crear un archivo de ruta de navegación
  5. Reiniciar
  6. Detecta el archivo de ruta de navegación
  7. Cómo comenzar a encriptar /data

    Luego, vold configura la asignación criptográfica, que crea un dispositivo virtual de bloques criptográficos. que se asigna al dispositivo de bloques real, pero que encripta cada sector a medida que está escrito, y desencripta cada sector a medida que se leen. Luego, vold crea y escribe los metadatos de criptografía.

  8. Mientras se encripta, activa tmpfs

    vold activa un /data de tmpfs (mediante las opciones de tmpfs). de ro.crypto.tmpfs_options) y establece la propiedad. vold.encrypt_progress a 0. vold prepara el tmpfs. /data para iniciar un sistema encriptado y establece la propiedad vold.decrypt a: trigger_restart_min_framework

  9. Agrega un marco de trabajo para mostrar el progreso

    trigger_restart_min_framework provoca que init.rc inicia la clase de servicios main. Cuando el framework ve que vold.encrypt_progress está configurado en 0, muestra la IU de la barra de progreso, que consulta esa propiedad cada cinco segundos y actualiza una barra de progreso. El bucle de encriptación actualiza vold.encrypt_progress cada vez que encripta otro porcentaje de la partición.

  10. Cuando /data esté encriptado, actualiza el pie de página de criptomonedas

    Cuando /data se encripta correctamente, vold borra la marca ENCRYPTION_IN_PROGRESS en los metadatos.

    Cuando el dispositivo se desbloquea correctamente, se usa la contraseña para encriptar la clave maestra y se actualiza el pie de página de criptografía.

    Si por algún motivo, falla el reinicio, vold establece la propiedad. vold.encrypt_progress a error_reboot_failed y la IU debe mostrar un mensaje en el que se le pida al usuario que presione un botón para reiniciar. No se espera que esto suceda.

Inicia un dispositivo encriptado con encriptación predeterminada

Esto es lo que sucede cuando inicias un dispositivo encriptado sin contraseña. Debido a que los dispositivos Android 5.0 se encriptan en el primer inicio, no debería haber una contraseña establecida y, por lo tanto, este es el estado de encriptación predeterminada.

  1. Cómo detectar /data encriptado sin contraseña

    Detecta que el dispositivo Android está encriptado porque no se puede activar /data y se estableció una de las marcas encryptable o forceencrypt.

    vold establece vold.decrypt en trigger_default_encryption, que da inicio a la servicio defaultcrypto. trigger_default_encryption comprueba el tipo de encriptación para ver si /data está encriptado con o sin una contraseña.

  2. Desencripta /data

    Crea el dispositivo dm-crypt sobre el dispositivo de almacenamiento en bloques para que el dispositivo está listo para usarse.

  3. Activa /data

    Luego, vold activa la partición /data real desencriptada y prepara la nueva. Establece la propiedad vold.post_fs_data_done en 0 y, luego, establece vold.decrypt a trigger_post_fs_data. Esto hace que init.rc ejecute sus comandos post-fs-data. Crean los directorios o vínculos necesarios y, luego, establecen vold.post_fs_data_done en 1.

    Una vez que vold ve el 1 en esa propiedad, establece la propiedad vold.decrypt en trigger_restart_framework.. Esto hace que init.rc vuelva a iniciar los servicios en la clase main y también inicie los servicios en la clase late_start por primera vez desde el inicio.

  4. Empieza a usar el framework

    Ahora, el framework inicia todos sus servicios con el /data desencriptado, y el sistema está listo para usarse.

Cómo iniciar un dispositivo encriptado sin encriptación predeterminada

Esto es lo que sucede cuando inicias un dispositivo encriptado que tiene una configuración contraseña. La contraseña del dispositivo puede ser un PIN, un patrón o una contraseña.

  1. Cómo detectar un dispositivo encriptado con una contraseña

    Detecta que el dispositivo Android está encriptado porque la marca ro.crypto.state = "encrypted"

    vold establece vold.decrypt en trigger_restart_min_framework porque /data es encriptado con una contraseña.

  2. Activar el tmpfs

    init establece cinco propiedades para guardar las opciones de activación iniciales. dado para /data con parámetros pasados desde init.rc. vold usa estas propiedades para configurar la asignación criptográfica:

    1. ro.crypto.fs_type
    2. ro.crypto.fs_real_blkdev
    3. ro.crypto.fs_mnt_point
    4. ro.crypto.fs_options
    5. ro.crypto.fs_flags (número hexadecimal de 8 dígitos ASCII precedido de 0x)
  3. Inicia el framework para solicitar la contraseña

    El framework se inicia y ve que vold.decrypt está configurado como trigger_restart_min_framework. Esto le indica al framework se inicia en un disco /data de tmpfs y necesita obtener la contraseña del usuario.

    Sin embargo, primero debe asegurarse de que el disco se haya encriptado correctamente. Envía el comando cryptfs cryptocomplete a vold. vold muestra 0 si la encriptación se completó correctamente, -1 en caso de error interno o -2 si la encriptación no se completó correctamente. vold determina buscando los metadatos criptográficos de CRYPTO_ENCRYPTION_IN_PROGRESS marca. Si está establecido, significa que se interrumpió el proceso de encriptación y no hay datos que se puedan usar en el dispositivo. Si vold muestra un error, la IU debe mostrarle un mensaje al usuario para que reinicie y restablezca la configuración de fábrica del dispositivo, y darle un botón para que lo haga.

  4. Desencripta datos con contraseña

    Una vez que cryptfs cryptocomplete se realiza correctamente, el framework muestra una IU que solicita la contraseña del disco. La IU verifica la contraseña enviando el comando cryptfs checkpw a vold. Si el botón contraseña sea correcta (lo que se determina activando con éxito el desencriptaste /data en una ubicación temporal y, luego, lo desactivaste) vold guarda el nombre del dispositivo de bloques desencriptado en la propiedad. ro.crypto.fs_crypto_blkdev y muestra el estado 0 a la IU. Si el botón es incorrecta, el resultado es -1 en la IU.

  5. Detén el framework

    La IU muestra un gráfico de inicio de criptografía y, luego, llama a vold con el comando cryptfs restart. vold establece la propiedad vold.decrypt en trigger_reset_main, lo que hace que init.rc haga class_reset main. Esta acción detendrá todos los servicios en la clase principal, lo que permite que se desactive el /data de tmpfs.

  6. Montaje /data

    Luego, vold activa la partición /data real desencriptada y prepara la partición nueva (que podría no haberse preparado si se encriptara con la opción de limpieza, que no es compatible con la primera versión). Establece la propiedad vold.post_fs_data_done en 0 y, luego, vold.decrypt en trigger_post_fs_data. Esto provoca init.rc para ejecutar sus comandos post-fs-data Crean los directorios o vínculos necesarios y, luego, establecen vold.post_fs_data_done en 1. Cuando vold vea el 1 de esa propiedad, establece la propiedad vold.decrypt en trigger_restart_framework Esto hace que init.rc vuelva a iniciar los servicios en la clase main y también inicie los servicios en la clase late_start por primera vez desde el inicio.

  7. Cómo iniciar el framework completo

    Ahora, el framework inicia todos sus servicios con el sistema de archivos /data descifrado, y el sistema está listo para usarse.

Error

Un dispositivo que no puede desencriptar puede estar fallando por varios motivos. El dispositivo comienza con la serie normal de pasos para iniciarse:

  1. Cómo detectar un dispositivo encriptado con una contraseña
  2. Activación de tmpfs
  3. Inicia el framework para solicitar una contraseña

Sin embargo, después de abrir el framework, es posible que el dispositivo encuentre algunos errores:

  • La contraseña coincide, pero no se pueden desencriptar los datos
  • El usuario ingresa una contraseña incorrecta 30 veces

Si no se resuelven estos errores, pide al usuario que borre la memoria de fábrica:

Si vold detecta un error durante el proceso de encriptación y si aún no se destruyeron datos y el framework está activo, vold establece la propiedad vold.encrypt_progress en error_not_encrypted. La IU le solicita al usuario que reinicie el dispositivo y le alerta que el proceso de encriptación nunca se inició. Si el error ocurre luego de que el framework se haya eliminado, pero antes de que la IU de la barra de progreso esté activa, vold reinicia el sistema. Si falla el reinicio, establece vold.encrypt_progress en error_shutting_down y muestra -1; pero no habrá nada para detectar el error. No se espera que esto suceda.

Si vold detecta un error durante el proceso de encriptación, establece vold.encrypt_progress a error_partially_encrypted y devuelve -1. Luego, la IU debería mostrar un mensaje que indique que la encriptación falló y proporcionar un botón para que el usuario restablezca la configuración de fábrica del dispositivo.

Almacena la clave encriptada

La clave encriptada se almacena en los metadatos criptográficos. El respaldo de hardware se implementa con la función de firma del entorno de ejecución confiable (TEE). Anteriormente, encriptamos la clave maestra con una clave generada aplicando scrypt a la contraseña del usuario y la sal almacenada. Para hacer que la clave sea resiliente contra ataques no convencionales, firmamos la clave resultante para extender este algoritmo con una clave de TEE almacenada. La firma resultante se convierte en un de una aplicación más de scrypt. Luego, esta clave se usa para encriptar y desencriptar la clave maestra. Para almacenar esta clave, haz lo siguiente:

  1. Generar una clave de encriptación de disco (DEK) aleatoria de 16 bytes y una sal de 16 bytes
  2. Aplica scrypt a la contraseña del usuario y a la sal para producir la clave intermedia 1 (IK1) de 32 bytes.
  3. Agrega un padding de IK1 con cero bytes al tamaño de la clave privada vinculada al hardware (HBK). En concreto, rellenamos como: 00 || IK1 || 00.00; un byte cero, 32 bytes IK1, 223 cero bytes.
  4. Firma el IK1 relleno con HBK para producir IK2 de 256 bytes.
  5. Aplica scrypt a IK2 y sal (la misma sal del paso 2) para producir IK3 de 32 bytes.
  6. Usa los primeros 16 bytes de IK3 como KEK y los últimos 16 bytes como IV.
  7. Encriptar DEK con AES_CBC, KEK clave y vector de inicialización IV

Cambiar la contraseña

Cuando un usuario elige cambiar o quitar su contraseña en la configuración, la IU envía el comando cryptfs changepw a vold, y vold vuelve a encriptar la clave maestra del disco con la contraseña nueva.

Propiedades de encriptación

vold y init se comunican entre sí configurando propiedades. Esta es una lista de las propiedades disponibles para la encriptación.

Propiedades de Vold

Propiedad Descripción
vold.decrypt trigger_encryption Encripta la unidad sin contraseña.
vold.decrypt trigger_default_encryption Revisa la unidad para ver si está encriptada sin contraseña. Si es así, desencripta y actívala. De lo contrario, configura vold.decrypt como trigger_restart_min_framework.
vold.decrypt trigger_reset_main Se configura mediante vold para apagar la IU que solicita la contraseña del disco.
vold.decrypt trigger_post_fs_data Se establece por vold para preparar /data con los directorios necesarios, et al.
vold.decrypt trigger_restart_framework Establecido por vold para iniciar el framework real y todos los servicios.
vold.decrypt trigger_shutdown_framework Configúralo por vold para cerrar todo el framework y comenzar la encriptación.
vold.decrypt trigger_restart_min_framework Se establece por vold para iniciar la IU de la barra de progreso para la encriptación solicitar la contraseña, según el valor de ro.crypto.state
vold.encrypt_progress Cuando se inicia el framework, Si esta propiedad está configurada, ingresa el modo de IU de la barra de progreso.
vold.encrypt_progress 0 to 100 La IU de la barra de progreso debería mostrar el valor porcentual establecido.
vold.encrypt_progress error_partially_encrypted La IU de la barra de progreso debe mostrar un mensaje que indique que la encriptación falló y darle al usuario la opción de restablecer el dispositivo de fábrica.
vold.encrypt_progress error_reboot_failed La IU de la barra de progreso debería mostrar un mensaje que indique la encriptación completar y darle al usuario un botón para reiniciar el dispositivo. Este error no se espera que suceda.
vold.encrypt_progress error_not_encrypted La IU de la barra de progreso debería mostrar un mensaje que dice un error no se encriptó ningún dato o perderse y darle al usuario un botón para reiniciar el sistema.
vold.encrypt_progress error_shutting_down La IU de la barra de progreso no se está ejecutando, por lo que no está claro quién responde a este error. Y nunca debería suceder de todas formas.
vold.post_fs_data_done 0 Establecido por vold justo antes de establecer vold.decrypt a trigger_post_fs_data.
vold.post_fs_data_done 1 Establecido por init.rc o init.rc justo después de terminar la tarea post-fs-data.

Propiedades de init

Propiedad Descripción
ro.crypto.fs_crypto_blkdev Establecido por el comando vold checkpw para su uso posterior por el comando restart de vold.
ro.crypto.state unencrypted Establecido por init para indicar que este sistema se ejecuta con un /data ro.crypto.state encrypted no encriptado. Se estableció por init para que diga este sistema se ejecuta con un /data encriptado.

ro.crypto.fs_type
ro.crypto.fs_real_blkdev
ro.crypto.fs_mnt_point
ro.crypto.fs_options
ro.crypto.fs_flags

Estas cinco propiedades se establecen init cuando intenta activar /data con parámetros pasados desde init.rc vold los usa para configurar la asignación criptográfica.
ro.crypto.tmpfs_options Establecido por init.rc con las opciones que init debe usar cuando activar el sistema de archivos /data de tmpfs.

Inicia las acciones.

on post-fs-data
on nonencrypted
on property:vold.decrypt=trigger_reset_main
on property:vold.decrypt=trigger_post_fs_data
on property:vold.decrypt=trigger_restart_min_framework
on property:vold.decrypt=trigger_restart_framework
on property:vold.decrypt=trigger_shutdown_framework
on property:vold.decrypt=trigger_encryption
on property:vold.decrypt=trigger_default_encryption