La encriptación total del disco es el proceso de codificación de todos los datos del usuario en un dispositivo Android con una 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 4.4, pero Android 5.0 presentó estas funciones nuevas:
- Se creó una encriptación rápida, que solo encripta los bloques usados en la partición de datos para evitar que el primer inicio tarde mucho tiempo. Actualmente, solo los sistemas de archivos ext4 y f2fs admiten 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ó el almacenamiento respaldado por hardware de la clave de encriptación con la función de firma del entorno de ejecución confiable (TEE) (como en una zona de confianza). Consulta Almacena la clave encriptada para obtener más detalles.
Precaución: Los dispositivos que se actualizaron a Android 5.0 y luego se encriptaron pueden volver a un estado sin encriptar mediante el restablecimiento de la configuración de fábrica. Los dispositivos nuevos con Android 5.0 que se encriptan en el primer inicio no se pueden devolver a un estado sin encriptar.
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 una función del kernel que funciona en la capa del dispositivo de almacenamiento en bloque. Debido a esto, la encriptación funciona con Embedded MultiMediaCard (eMMC) y dispositivos flash similares que se presentan al kernel como dispositivos de bloques. 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 (256 es opcional).
Nota: Los OEMs pueden usar 128 bits o más para encriptar la clave principal.
En la versión 5.0 de Android, hay cuatro tipos de estados de encriptación:
- default
- PIN
- contraseña
- patrón
Durante el primer inicio, el dispositivo crea una clave maestra de 128 bits generada de forma aleatoria y, luego, la hashea con una contraseña predeterminada y una 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 o la contraseña en el dispositivo, solo se vuelve a encriptar y almacenar la clave de 128 bits. (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 analizan las propiedades para realizar tareas como informar el estado, solicitar una contraseña o solicitar el restablecimiento de la configuración de fábrica en caso de un error irrecuperable. 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 borrar /data
, /data
no debe estar activado. 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 deben estar en uno de los tres grupos: core
, main
y late_start
.
core
: Nunca se apague después de iniciarse.main
: Apaga el dispositivo y, luego, reinícialo después de ingresar la contraseña del disco.late_start
: No se inicia hasta que se desencripta y se activa/data
.
Para activar estas acciones, la propiedad vold.decrypt
se establece en varias cadenas.
Para finalizar y reiniciar servicios, los comandos 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 marcaSVC_DISABLED
. Los servicios detenidos no responden aclass_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:
- Encripta un dispositivo nuevo con
forceencrypt
: Encriptación obligatoria en el primer inicio (a partir de Android L). - Encripta un dispositivo existente: Encriptación iniciada por el usuario (Android K y versiones anteriores).
- Encripta un dispositivo nuevo con
- Cómo iniciar un dispositivo encriptado:
- Inicio de un dispositivo encriptado sin contraseña: Inicio de 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, el dispositivo también puede no encriptar /data
.
A continuación, se explica cada uno de los flujos en detalle.
Encripta un dispositivo nuevo con forceencrypt
Este es el primer inicio normal de un dispositivo con Android 5.0.
- Cómo detectar un sistema de archivos no encriptado con la marca
forceencrypt
/data
no está encriptado, pero debe estarlo porqueforceencrypt
lo exige. Desactiva/data
. - Cómo comenzar a encriptar
/data
vold.decrypt = "trigger_encryption"
activainit.rc
, lo que hace quevold
encripte/data
sin contraseña. (No se establece ninguno porque este debe ser un dispositivo nuevo). - Activa tmpfs
vold
activa un/data
de tmpfs (con las opciones de tmpfs dero.crypto.tmpfs_options
) y establece la propiedadvold.encrypt_progress
en 0.vold
prepara el tmpfs/data
para iniciar un sistema encriptado y establece la propiedadvold.decrypt
entrigger_restart_min_framework
. - 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.
- Cuando
/data
esté encriptado, quita el frameworkvold
establecevold.decrypt
entrigger_default_encryption
, que inicia el serviciodefaultcrypto
. (Esto inicia el siguiente flujo para activar un archivo de datos del usuario encriptado 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
. - Montaje
/data
Luego,
init
activa/data
en un disco RAM tmpfs con los parámetros que toma dero.crypto.tmpfs_options
, que se configura eninit.rc
. - Empieza a usar el framework
vold
establecevold.decrypt
entrigger_restart_framework
, que continúa con el proceso de inicio habitual.
Cómo encriptar 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 en el lugar” 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 init
on nonencrypted
para continuar con el inicio.
- Verificar contraseña
La IU llama a
vold
con el comandocryptfs enablecrypto inplace
, en el quepasswd
es la contraseña de la pantalla de bloqueo del usuario. - Cómo quitar el framework
vold
busca errores, muestra -1 si no puede encriptar y imprime un motivo en el registro. Si puede encriptar, configura la propiedadvold.decrypt
comotrigger_shutdown_framework
. Esto hace queinit.rc
detenga los servicios en las claseslate_start
ymain
. - Cómo crear un pie de página criptográfico
- Cómo crear un archivo de migas de pan
- Reinicio
- Cómo detectar el archivo de ruta de navegación
- Cómo comenzar a encriptar
/data
Luego,
vold
configura la asignación 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 se escribe y desencripta cada sector a medida que se lee. Luego,vold
crea y escribe los metadatos de criptografía. - Mientras se encripta, activa tmpfs
vold
activa un/data
de tmpfs (con las opciones de tmpfs dero.crypto.tmpfs_options
) y establece la propiedadvold.encrypt_progress
en 0.vold
prepara el tmpfs/data
para iniciar un sistema encriptado y establece la propiedadvold.decrypt
entrigger_restart_min_framework
. - Cómo mostrar el framework para mostrar el progreso
trigger_restart_min_framework
hace queinit.rc
inicie la clase de serviciosmain
. Cuando el framework ve quevold.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 actualizavold.encrypt_progress
cada vez que encripta otro porcentaje de la partición. - Cuando
/data
esté encriptado, actualiza el pie de página de criptografíaCuando
/data
se encripta correctamente,vold
borra la marcaENCRYPTION_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 criptográfico.
Si el reinicio falla por algún motivo,
vold
establece la propiedadvold.encrypt_progress
enerror_reboot_failed
y la IU debe mostrar un mensaje que le solicite al usuario que presione un botón para reiniciar. No se espera que esto suceda.
Cómo iniciar 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.
- Cómo detectar
/data
encriptado sin contraseñaDetecta que el dispositivo Android está encriptado porque no se puede activar
/data
y se estableció una de las marcasencryptable
oforceencrypt
.vold
establecevold.decrypt
entrigger_default_encryption
, que inicia el serviciodefaultcrypto
.trigger_default_encryption
verifica el tipo de encriptación para ver si/data
está encriptado con o sin una contraseña. - Desencripta /data
Crea el dispositivo
dm-crypt
sobre el dispositivo de almacenamiento en bloques para que esté listo para usarse. - Activa /data
Luego,
vold
activa la partición/data
real desencriptada y prepara la nueva. Establece la propiedadvold.post_fs_data_done
en 0 y, luego, establecevold.decrypt
entrigger_post_fs_data
. Esto hace queinit.rc
ejecute sus comandospost-fs-data
. Crean los directorios o vínculos necesarios y, luego, establecenvold.post_fs_data_done
en 1.Una vez que
vold
ve el 1 en esa propiedad, establece la propiedadvold.decrypt
entrigger_restart_framework.
. Esto hace queinit.rc
vuelva a iniciar los servicios en la clasemain
y también inicie los servicios en la claselate_start
por primera vez desde el inicio. - 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 contraseña establecida. La contraseña del dispositivo puede ser un PIN, un patrón o una contraseña.
- 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
establecevold.decrypt
entrigger_restart_min_framework
porque/data
está encriptado con una contraseña. - Activa tmpfs
init
establece cinco propiedades para guardar las opciones de activación iniciales proporcionadas para/data
con parámetros pasados desdeinit.rc
.vold
usa estas propiedades para configurar la asignación de criptografía:ro.crypto.fs_type
ro.crypto.fs_real_blkdev
ro.crypto.fs_mnt_point
ro.crypto.fs_options
ro.crypto.fs_flags
(número hexadecimal de 8 dígitos ASCII precedido de 0x)
- Cómo iniciar el framework para solicitar una contraseña
El framework se inicia y ve que
vold.decrypt
está configurado comotrigger_restart_min_framework
. Esto le indica al framework que se está iniciando en un disco/data
de tmpfs y que debe 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
avold
.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 esto buscando la marcaCRYPTO_ENCRYPTION_IN_PROGRESS
en los metadatos de criptografía. Si está establecido, significa que el proceso de encriptación se interrumpió y no hay datos que se puedan usar en el dispositivo. Sivold
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. - Cómo desencriptar datos con una 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 comandocryptfs checkpw
avold
. Si la contraseña es correcta (lo que se determina cuando se activa correctamente el/data
desencriptado en una ubicación temporal y, luego, se desactiva),vold
guarda el nombre del dispositivo de almacenamiento en bloque desencriptado en la propiedadro.crypto.fs_crypto_blkdev
y muestra el estado 0 en la IU. Si la contraseña es incorrecta, se muestra -1 en la IU. - Detener el framework
La IU muestra un gráfico de inicio de criptografía y, luego, llama a
vold
con el comandocryptfs restart
.vold
establece la propiedadvold.decrypt
entrigger_reset_main
, lo que hace queinit.rc
hagaclass_reset main
. Esto detiene todos los servicios de la clase principal, lo que permite que se desmonte el tmpfs/data
. - 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 propiedadvold.post_fs_data_done
en 0 y, luego,vold.decrypt
entrigger_post_fs_data
. Esto hace queinit.rc
ejecute sus comandospost-fs-data
. Crean los directorios o vínculos necesarios y, luego, establecenvold.post_fs_data_done
en 1. Cuandovold
ve el 1 en esa propiedad, establece la propiedadvold.decrypt
entrigger_restart_framework
. Esto hace queinit.rc
vuelva a iniciar los servicios en la clasemain
y también inicie los servicios en la claselate_start
por primera vez desde el inicio. - 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:
- Cómo detectar un dispositivo encriptado con una contraseña
- Activación de tmpfs
- Inicia el framework para solicitar una contraseña
Sin embargo, después de que se abre el framework, el dispositivo puede encontrar 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 se produce después de que se desmontó el framework, pero antes de que se active la IU de la barra de progreso, vold
reinicia el sistema. Si falla el reinicio, se establece vold.encrypt_progress
en error_shutting_down
y se muestra -1, pero no habrá nada para detectar el error. Esto no debería suceder.
Si vold
detecta un error durante el proceso de encriptación, establece vold.encrypt_progress
en error_partially_encrypted
y muestra -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 de criptografía. La copia de seguridad 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 que la clave sea resistente a los ataques fuera de la caja, extendemos este algoritmo firmando la clave resultante con una clave TEE almacenada. La firma resultante se convierte en una clave de longitud adecuada con 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:
- Genera una clave de encriptación de disco (DEK) y una sal de 16 bytes aleatorias.
- Aplica scrypt a la contraseña del usuario y a la sal para producir la clave intermedia 1 (IK1) de 32 bytes.
- Agrega un padding de IK1 con cero bytes al tamaño de la clave privada vinculada al hardware (HBK). Específicamente, agregamos padding de la siguiente manera: 00 || IK1 || 00..00; un byte cero, 32 bytes IK1, 223 bytes cero.
- Firma el IK1 con padding con HBK para producir un IK2 de 256 bytes.
- Aplica scrypt a IK2 y a la sal (la misma sal que en el paso 2) para producir IK3 de 32 bytes.
- Usa los primeros 16 bytes de IK3 como KEK y los últimos 16 bytes como IV.
- Encripta la DEK con AES_CBC, con la clave KEK y el vector de inicialización IV.
Cambia la contraseña
Cuando un usuario decide 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. A continuación, se muestra 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 |
Verifica la unidad para ver si está encriptada sin contraseña.
Si es así, desencripta y activa el sistema de archivos. De lo contrario, establece vold.decrypt en trigger_restart_min_framework. |
vold.decrypt trigger_reset_main |
Establecido por vold para cerrar 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, etcétera. |
vold.decrypt trigger_restart_framework |
Establecido por vold para iniciar el framework real y todos los servicios. |
vold.decrypt trigger_shutdown_framework |
Se establece por vold para cerrar el framework completo y comenzar la encriptación. |
vold.decrypt trigger_restart_min_framework |
Es establecido por vold para iniciar la IU de la barra de progreso de encriptación o solicitar una contraseña, según el valor de ro.crypto.state . |
vold.encrypt_progress |
Cuando se inicia el framework, si se configura esta propiedad, ingresa al 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 debe mostrar un mensaje que indique que se completó la encriptación 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 IU de la barra de progreso debe mostrar un mensaje que indique que se produjo un error, que no se encriptaron ni se perdieron datos, 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, 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 terminar la tarea post-fs-data . |
Propiedades de init
Propiedad | Descripción |
---|---|
ro.crypto.fs_crypto_blkdev |
Es establecido por el comando vold checkpw para que lo use más adelante el comando vold restart . |
ro.crypto.state unencrypted |
Establecido por init para indicar que este sistema se ejecuta con un /data ro.crypto.state encrypted no encriptado. Establecido por init para indicar que este sistema se ejecuta con un /data encriptado. |
|
init establece estas cinco propiedades cuando intenta activar /data con parámetros pasados desde init.rc . vold los usa para configurar el mapeo de criptografía. |
ro.crypto.tmpfs_options |
Establecido por init.rc con las opciones que init debe usar cuando activa el sistema de archivos /data de tmpfs. |
Acciones de init
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