Google is committed to advancing racial equity for Black communities. See how.
Se usó la API de Cloud Translation para traducir esta página.
Switch to English

Cifrado de disco completo

El cifrado de disco completo es el proceso de codificar todos los datos del usuario en un dispositivo Android mediante una clave cifrada. Una vez que un dispositivo está cifrado, todos los datos creados por el usuario se cifran automáticamente antes de enviarlos al disco y todas las lecturas descifran automáticamente los datos antes de devolverlos al proceso de llamada.

El cifrado de disco completo se introdujo en Android en 4.4, pero Android 5.0 introdujo estas nuevas características:

  • Se creó un cifrado rápido, que solo cifra los bloques usados ​​en la partición de datos para evitar que el primer arranque tarde mucho tiempo. Actualmente, solo los sistemas de archivos ext4 y f2fs admiten el cifrado rápido.
  • Se agregó el forceencrypt fstab para cifrar en el primer arranque.
  • Se agregó soporte para patrones y cifrado sin contraseña.
  • Se agregó almacenamiento respaldado por hardware de la clave de cifrado utilizando la capacidad de firma de Trusted Execution Environment (TEE) (como en un TrustZone). Consulte Almacenamiento de la clave cifrada para obtener más detalles.

Precaución: los dispositivos actualizados a Android 5.0 y luego cifrados pueden volver a un estado no cifrado mediante el restablecimiento de datos de fábrica. Los nuevos dispositivos Android 5.0 cifrados en el primer arranque no se pueden devolver a un estado sin cifrar.

Cómo funciona el cifrado de disco completo de Android

El cifrado de disco completo de Android se basa en dm-crypt , que es una característica del kernel que funciona en la capa del dispositivo de bloque. Debido a esto, el cifrado funciona con Embedded MultiMediaCard ( eMMC) y dispositivos flash similares que se presentan al kernel como dispositivos de bloque. El cifrado no es posible con YAFFS, que se comunica directamente con un chip flash NAND sin procesar.

El algoritmo de cifrado es 128 Advanced Encryption Standard (AES) con encadenamiento de bloques de cifrado (CBC) y ESSIV: SHA256. La clave maestra está encriptada con AES de 128 bits mediante llamadas a la biblioteca OpenSSL. Debe utilizar 128 bits o más para la clave (siendo 256 opcional).

Nota: Los fabricantes de equipos originales pueden utilizar 128 bits o superior para cifrar la clave maestra.

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

  • defecto
  • ALFILER
  • contraseña
  • patrón

En el primer arranque, el dispositivo crea una clave maestra de 128 bits generada aleatoriamente y luego la codifica con una contraseña predeterminada y 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 utiliza un hash de la firma para cifrar la clave maestra.

Puede 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 / contraseña o contraseña en el dispositivo, solo se vuelve a cifrar y almacenar la clave de 128 bits. (es decir, los cambios de PIN / contraseña / patrón de usuario NO causan que se vuelva a cifrar los datos del usuario). Tenga en cuenta que el dispositivo administrado puede estar sujeto a restricciones de PIN, patrón o contraseña.

El cifrado es administrado por init y vold . init llama a vold , y vold establece propiedades para desencadenar eventos en init. Otras partes del sistema también miran las propiedades para realizar tareas como informar el estado, solicitar una contraseña o solicitar el restablecimiento de fábrica en caso de un error fatal. Para invocar funciones de cifrado en vold , el sistema utiliza 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 cifrar, descifrar o borrar /data , /data no se debe montar. Sin embargo, para mostrar cualquier interfaz de usuario (UI), el marco debe iniciarse y el marco requiere /data para ejecutarse. Para resolver este enigma, se monta un sistema de archivos temporal en /data . Esto permite que Android solicite contraseñas, muestre el progreso o sugiera una eliminación de datos según sea necesario. Impone la limitación de que para cambiar del sistema de archivos temporal al sistema de archivos verdadero /data , el sistema debe detener todos los procesos con archivos abiertos en el sistema de archivos temporal y reiniciar esos procesos en el sistema de archivos real /data . Para hacer esto, todos los servicios deben estar en uno de tres grupos: core , main y late_start .

  • core : Nunca apague después de comenzar.
  • main : Apague y luego reinicie después de ingresar la contraseña del disco.
  • late_start : no se inicia hasta que /data se ha descifrado y montado.

Para activar estas acciones, la propiedad vold.decrypt se establece en varias cadenas . Para matar y reiniciar los servicios, los comandos init son:

  • 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 un indicador SVC_DISABLED . Los servicios detenidos no responden a class_start .

Flujos

Hay cuatro flujos para un dispositivo cifrado. Un dispositivo se cifra solo una vez y luego sigue un flujo de arranque normal.

  • Cifre un dispositivo previamente no cifrado:
    • Cifre un nuevo dispositivo con forceencrypt : cifrado obligatorio en el primer arranque (a partir de Android L).
    • Cifrar un dispositivo existente: cifrado iniciado por el usuario (Android K y versiones anteriores).
  • Inicie un dispositivo encriptado:
    • Iniciar un dispositivo cifrado sin contraseña: iniciar un dispositivo cifrado que no tiene una contraseña establecida (relevante para dispositivos con Android 5.0 y posterior).
    • Iniciar un dispositivo cifrado con una contraseña: iniciar un dispositivo cifrado que tiene una contraseña establecida.

Además de estos flujos, el dispositivo también puede fallar al cifrar /data . Cada uno de los flujos se explica en detalle a continuación.

Cifre un nuevo dispositivo con forceencrypt

Este es el primer arranque normal para un dispositivo Android 5.0.

  1. Detecta el sistema de archivos no cifrado con la bandera forceencrypt

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

  2. Comience a cifrar /data

    vold.decrypt = "trigger_encryption" activa init.rc , que hará que vold cifre /data sin contraseña. (Ninguno está configurado porque debe ser un dispositivo nuevo).

  3. Monte tmpfs

    vold monta un tmpfs /data (usando las opciones tmpfs de ro.crypto.tmpfs_options ) y establece la propiedad vold.encrypt_progress en 0. vold prepara los tmpfs /data para iniciar un sistema cifrado y establece la propiedad vold.decrypt en: trigger_restart_min_framework

  4. Trae el marco para mostrar el progreso

    Debido a que el dispositivo prácticamente no tiene datos para cifrar, la barra de progreso a menudo no aparecerá porque el cifrado ocurre muy rápido. Consulte Cifrar un dispositivo existente para obtener más detalles sobre la IU de progreso.

  5. Cuando /data esté encriptado, elimine el marco

    vold establece vold.decrypt en trigger_default_encryption que inicia el servicio defaultcrypto . (Esto inicia el flujo a continuación para montar datos de usuario encriptados predeterminados). trigger_default_encryption verifica el tipo de encriptación para ver si /data está encriptado con o sin contraseña. Debido a que los dispositivos Android 5.0 están encriptados en el primer arranque, no debería haber una contraseña establecida; por lo tanto, desencriptamos y montamos /data .

  6. Montaje /data

    init luego monta /data en un RAMDisk tmpfs usando los parámetros que toma de ro.crypto.tmpfs_options , que se establece en init.rc

  7. Iniciar marco

    Configure vold en trigger_restart_framework , que continúa con el proceso de arranque habitual.

Cifrar un dispositivo existente

Esto es lo que sucede cuando se cifra un dispositivo Android K sin cifrar o un dispositivo anterior que se ha migrado a L.

Este proceso lo inicia el usuario y se denomina "encriptación in situ" en el código. Cuando un usuario selecciona cifrar un dispositivo, la interfaz de usuario se asegura de que la batería esté completamente cargada y el adaptador de CA esté enchufado para que haya suficiente energía para finalizar el proceso de cifrado.

Advertencia: si el dispositivo se queda sin energía y se apaga antes de que haya terminado de cifrar, los datos del archivo se dejan en un estado parcialmente cifrado. El dispositivo debe restablecerse de fábrica y se perderán todos los datos.

Para habilitar el cifrado in situ, vold inicia un bucle para leer cada sector del dispositivo de bloque real y luego escribirlo en el dispositivo de bloque de cifrado. vold comprueba si un sector está en uso antes de leerlo y escribirlo, lo que hace que el cifrado sea mucho más rápido en un dispositivo nuevo que tiene pocos o ningún dato.

Estado del dispositivo : ro.crypto.state = "unencrypted" y ejecute el on nonencrypted init on nonencrypted para continuar con el arranque.

  1. Comprobar contraseña

    La interfaz de usuario llama a vold con el comando cryptfs enablecrypto inplace donde passwd es la contraseña de la pantalla de bloqueo del usuario.

  2. Derriba el marco

    vold comprueba si hay errores, devuelve -1 si no puede cifrar e imprime una razón en el registro. Si puede cifrar, establece la propiedad vold.decrypt en trigger_shutdown_framework . Esto hace que init.rc detenga los servicios en las clases late_start y main .

  3. Crea un pie de página criptográfico
  4. Crea un archivo de ruta de navegación
  5. Reiniciar
  6. Detectar archivo de ruta de navegación
  7. Comience a cifrar /data

    vold luego configura el mapeo de criptografía, que crea un dispositivo de bloque de criptografía virtual que se asigna al dispositivo de bloque real pero encripta cada sector a medida que está escrito y descifra cada sector a medida que se lee. vold luego crea y escribe los metadatos criptográficos.

  8. Mientras está encriptando, monte tmpfs

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

  9. Trae el marco para mostrar el progreso

    trigger_restart_min_framework hace que init.rc inicie la clase main de servicios. Cuando el marco ve que vold.encrypt_progress está establecido en 0, muestra la interfaz de usuario de la barra de progreso, que consulta esa propiedad cada cinco segundos y actualiza una barra de progreso. El ciclo de cifrado actualiza vold.encrypt_progress cada vez que cifra otro porcentaje de la partición.

  10. Cuando /data esté encriptado, actualice el pie de página criptográfico

    Cuando /data se cifran con éxito, vold borra la bandera ENCRYPTION_IN_PROGRESS en los metadatos.

    Cuando el dispositivo se desbloquea con éxito, la contraseña se utiliza para cifrar la clave maestra y se actualiza el pie de página de cifrado.

    Si el reinicio falla por algún motivo, vold establece la propiedad vold.encrypt_progress en error_reboot_failed y la interfaz de usuario debería mostrar un mensaje pidiendo al usuario que presione un botón para reiniciar. No se espera que esto suceda nunca.

Iniciar un dispositivo cifrado con cifrado predeterminado

Esto es lo que sucede cuando inicia un dispositivo encriptado sin contraseña. Debido a que los dispositivos Android 5.0 se cifran en el primer arranque, no debe haber una contraseña establecida y, por lo tanto, este es el estado de cifrado predeterminado .

  1. Detecta /data cifrados sin contraseña

    Detecta que el dispositivo Android está encriptado porque /data no se puede montar y uno de los indicadores encryptable o forceencrypt está configurado.

    vold establece vold.decrypt en trigger_default_encryption , que inicia el servicio defaultcrypto . trigger_default_encryption comprueba el tipo de cifrado para ver si /data está cifrado con o sin contraseña.

  2. Descifrar / datos

    Crea el dispositivo dm-crypt sobre el dispositivo de bloque para que el dispositivo esté listo para su uso.

  3. Montaje / datos

    vold luego monta la partición real /data descifrada y luego prepara la nueva partición. Establece la propiedad vold.post_fs_data_done en 0 y luego establece vold.decrypt en trigger_post_fs_data . Esto hace que init.rc ejecute sus comandos post-fs-data . vold.post_fs_data_done directorios o enlaces necesarios y luego establecerán 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 inicie los servicios en la clase main nuevamente y también inicie los servicios en la clase late_start por primera vez desde el inicio.

  4. Iniciar marco

    Ahora el marco arranca todos sus servicios utilizando los /data descifrados, y el sistema está listo para su uso.

Iniciar un dispositivo cifrado sin cifrado predeterminado

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

  1. Detectar dispositivo encriptado con contraseña

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

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

  2. Monte tmpfs

    init establece cinco propiedades para guardar las opciones de montaje iniciales dadas para /data con parámetros pasados ​​desde init.rc vold usa estas propiedades para configurar el mapeo criptográfico:

    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 por 0x)
  3. Inicie el marco para solicitar la contraseña

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

    Sin embargo, primero debe asegurarse de que el disco esté encriptado correctamente. Envía el comando cryptfs cryptocomplete a vold . vold devuelve 0 si el cifrado se completó correctamente, -1 en caso de error interno o -2 si el cifrado no se completó correctamente. vold determina esto buscando en los metadatos criptográficos el indicador CRYPTO_ENCRYPTION_IN_PROGRESS . Si está configurado, el proceso de cifrado se interrumpió y no hay datos utilizables en el dispositivo. Si vold devuelve un error, la interfaz de usuario debe mostrar un mensaje al usuario para que reinicie y restablezca la configuración de fábrica del dispositivo, y darle al usuario un botón para presionar para hacerlo.

  4. Descifrar datos con contraseña

    Una vez que cryptfs cryptocomplete es exitoso, el marco muestra una interfaz de usuario que solicita la contraseña del disco. La interfaz de usuario verifica la contraseña enviando el comando cryptfs checkpw a vold . Si la contraseña es correcta (que se determina montando con éxito los /data descifrados en una ubicación temporal y luego vold ), vold guarda el nombre del dispositivo de bloque descifrado en la propiedad ro.crypto.fs_crypto_blkdev y devuelve el estado 0 a la interfaz de usuario . Si la contraseña es incorrecta, devuelve -1 a la interfaz de usuario.

  5. Detener marco

    La interfaz de usuario vold un gráfico de arranque criptográfico 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 . Esto detiene todos los servicios de la clase principal, lo que permite desmontar tmpfs /data .

  6. Montaje /data

    vold luego monta la partición real /data descifrada y prepara la nueva partición (que puede que nunca se haya preparado si se cifró con la opción de borrado, que no es compatible con la primera versión). Establece la propiedad vold.post_fs_data_done en 0 y luego establece vold.decrypt en trigger_post_fs_data . Esto hace que init.rc ejecute sus comandos post-fs-data . vold.post_fs_data_done directorios o enlaces necesarios y luego establecerán 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 inicie los servicios en la clase main nuevamente y también inicie los servicios en la clase late_start por primera vez desde el inicio.

  7. Iniciar marco completo

    Ahora el marco arranca todos sus servicios utilizando el sistema de archivos de /data descifrado, y el sistema está listo para su uso.

Fracaso

Un dispositivo que no se puede descifrar puede estar mal por varias razones. El dispositivo comienza con la serie normal de pasos para arrancar:

  1. Detectar dispositivo encriptado con contraseña
  2. Monte tmpfs
  3. Inicie el marco para solicitar la contraseña

Pero una vez que se abre el marco, el dispositivo puede encontrar algunos errores:

  • La contraseña coincide pero no puede descifrar los datos
  • El usuario ingresa una contraseña incorrecta 30 veces

Si estos errores no se resuelven, solicite al usuario que limpie de fábrica :

Si vold detecta un error durante el proceso de cifrado, y si aún no se han destruido datos y el marco está activo, vold establece la propiedad vold.encrypt_progress en error_not_encrypted . La interfaz de usuario solicita al usuario que reinicie y le advierte que el proceso de cifrado nunca se inició. Si el error se produce después de que se haya derribado el marco, pero antes de que se vold interfaz de usuario de la barra de progreso, vold reiniciará el sistema. Si el reinicio falla, establece vold.encrypt_progress en error_shutting_down y devuelve -1; pero no habrá nada para detectar el error. No se espera que esto suceda.

Si vold detecta un error durante el proceso de cifrado, establece vold.encrypt_progress en error_partially_encrypted y devuelve -1. La interfaz de usuario debe mostrar un mensaje que indique que el cifrado falló y proporcionar un botón para que el usuario restablezca el dispositivo de fábrica.

Almacenamiento de la clave encriptada

La clave cifrada se almacena en los metadatos criptográficos. El respaldo de hardware se implementa mediante el uso de la capacidad de firma de Trusted Execution Environment (TEE). Anteriormente, ciframos la clave maestra con una clave generada al aplicar scrypt a la contraseña del usuario y al salt almacenado. Para hacer que la clave sea resistente contra ataques fuera de la caja, ampliamos este algoritmo firmando la clave resultante con una clave TEE almacenada. La firma resultante se convierte luego en una clave de longitud adecuada mediante una aplicación más de scrypt. Luego, esta clave se usa para cifrar y descifrar la clave maestra. Para almacenar esta clave:

  1. Genere una clave de cifrado de disco (DEK) aleatoria de 16 bytes y sal de 16 bytes.
  2. Aplique scrypt a la contraseña de usuario y la sal para producir la clave intermedia 1 de 32 bytes (IK1).
  3. Rellene IK1 con cero bytes al tamaño de la clave privada vinculada al hardware (HBK). Específicamente, rellenamos como: 00 || IK1 || 00..00; un byte cero, 32 bytes IK1, 223 bytes cero.
  4. Firme IK1 acolchado con HBK para producir IK2 de 256 bytes.
  5. Aplique scrypt a IK2 y sal (la misma sal que en el paso 2) para producir IK3 de 32 bytes.
  6. Utilice los primeros 16 bytes de IK3 como KEK y los últimos 16 bytes como IV.
  7. Cifre DEK con AES_CBC, con la clave KEK y el vector de inicialización IV.

Cambiar la contraseña

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

Propiedades de cifrado

vold e init comunican entre sí estableciendo propiedades. A continuación, se muestra una lista de propiedades disponibles para el cifrado.

Propiedades Vold

Propiedad Descripción
vold.decrypt trigger_encryption Cifre la unidad sin contraseña.
vold.decrypt trigger_default_encryption Verifique la unidad para ver si está encriptada sin contraseña. Si es así, descifrelo y vold.decrypt ; de lo contrario, configure vold.decrypt en trigger_restart_min_framework.
vold.decrypt trigger_reset_main Establecido por vold para apagar la IU solicitando la contraseña del disco.
vold.decrypt trigger_post_fs_data Establecido por vold para preparar /data con los directorios necesarios, et al.
vold.decrypt trigger_restart_framework Establecido por vold para iniciar el marco real y todos los servicios.
vold.decrypt trigger_shutdown_framework Establecido por vold para apagar el marco completo para iniciar el cifrado.
vold.decrypt trigger_restart_min_framework Establecido por vold para iniciar la interfaz de usuario de la barra de progreso para el cifrado o solicitar la contraseña, según el valor de ro.crypto.state .
vold.encrypt_progress Cuando se inicia el marco, si se establece esta propiedad, ingrese al modo de interfaz de usuario de la barra de progreso.
vold.encrypt_progress 0 to 100 La interfaz de usuario de la barra de progreso debe mostrar el valor de porcentaje establecido.
vold.encrypt_progress error_partially_encrypted La interfaz de usuario de la barra de progreso debe mostrar un mensaje de que el cifrado falló y darle al usuario la opción de restablecer el dispositivo de fábrica.
vold.encrypt_progress error_reboot_failed La interfaz de usuario de la barra de progreso debe mostrar un mensaje que diga que se completó el cifrado y darle al usuario un botón para reiniciar el dispositivo. No se espera que ocurra este error.
vold.encrypt_progress error_not_encrypted La interfaz de usuario de la barra de progreso debe mostrar un mensaje que indique que se produjo un error, que no se cifraron ni se perdieron datos, y que el usuario tenga un botón para reiniciar el sistema.
vold.encrypt_progress error_shutting_down La interfaz de usuario de la barra de progreso no se está ejecutando, por lo que no está claro quién responderá a este error. Y de todos modos, nunca debería suceder.
vold.post_fs_data_done 0 Establecido por vold justo antes de establecer vold.decrypt en trigger_post_fs_data .
vold.post_fs_data_done 1 Establecido por init.rc o init.rc justo después de finalizar la tarea post-fs-data .

propiedades de inicio

Propiedad Descripción
ro.crypto.fs_crypto_blkdev Establecido por el vold comando checkpw para su uso posterior por el vold comando de restart .
ro.crypto.state unencrypted Establecido por init para decir que este sistema se está ejecutando con un /data ro.crypto.state encrypted . Establecido por init para decir que este sistema se está ejecutando con un /data .

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 las establece init cuando intenta montar /data con parámetros pasados ​​desde init.rc vold usa para configurar el mapeo criptográfico.
ro.crypto.tmpfs_options Establecido por init.rc con las opciones que init debe usar al montar el sistema de archivos tmpfs /data .

Acciones de inicio

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