La encriptación de disco completo es el proceso de codificar todos los datos del usuario en un dispositivo Android utilizando una clave encriptada. Una vez que el dispositivo está encriptado, todos los datos creados por el usuario se encriptan automáticamente antes de consignarlos en el disco y todas las lecturas descifran automáticamente los datos antes de devolverlos al proceso de llamada.
La encriptación de disco completo se introdujo en Android en la versión 4.4, pero Android 5.0 introdujo estas nuevas características:
- Encriptación rápida creada, que sólo encripta los bloques utilizados en la partición de datos para evitar que el primer arranque tarde mucho tiempo. Sólo los sistemas de archivos ext4 y f2fs soportan actualmente el cifrado rápido.
- Agregado el indicador
forceencrypt
fstab para encriptar en el primer arranque. - Se ha añadido soporte para patrones y encriptación sin contraseña.
- Agregado el almacenamiento respaldado por hardware de la clave de cifrado utilizando la capacidad de firma de Trusted Execution Environment (TEE) (como en una TrustZone). Consulte Almacenamiento de la clave cifrada para obtener más detalles.
Precaución: Los dispositivos actualizados a Android 5.0 y luego encriptados pueden volver a un estado no encriptado mediante el restablecimiento de datos de fábrica. Los nuevos dispositivos Android 5.0 encriptados en el primer arranque no pueden volver a un estado sin encriptar.
- Cómo funciona la encriptación de disco completo de Android
- Flows
- Encriptar un nuevo dispositivo con forceencrypt
- Encriptar un dispositivo existente
- Inicio de un dispositivo encriptado con encriptación por defecto
- Iniciar un dispositivo encriptado sin encriptación por defecto
- Fallo
- Almacenamiento de la clave encriptada
- Cambiar la contraseña
- Propiedades de cifrado
- Propiedades de cifrado
- Propiedades de init
- Acciones de init
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 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 habla 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 se cifra 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 OEM pueden utilizar 128 bits o más para cifrar la clave maestra.
En la versión de Android 5.0, hay cuatro tipos de estados de cifrado:
- Por defecto
- PIN
- contraseña
- patrón
Al arrancar por primera vez, el dispositivo crea una clave maestra de 128 bits generada aleatoriamente y, a continuación, la hashifica con una contraseña por defecto y una sal almacenada. La contraseña por defecto 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 por defecto definida en el archivo cryptfs.cpp del proyecto Android Open Source.
Cuando el usuario establece el PIN/pass o la contraseña en el dispositivo, sólo se vuelve a cifrar y almacenar la clave de 128 bits. (es decir, los cambios de PIN/pass/patrón del usuario NO causan la recodificación de los datos del usuario). Tenga en cuenta que el dispositivo administrado puede estar sujeto a restricciones de PIN, patrón o contraseña.
La codificación es administrada 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 llevar a cabo tareas como informar del estado, pedir una contraseña o pedir el restablecimiento de fábrica en caso de un error fatal. Para invocar las funciones de cifrado en vold
, el sistema utiliza los comandos cryptfs
de la herramienta de línea de comandos: checkpw
,restart
, enablecrypto
, changepw
,cryptocomplete
, verifypw
, setfield
,getfield
, mountdefaultencrypted
, getpwtype
,getpw
y clearpw
.
Para cifrar, descifrar o borrar /data
, /data
no debe estar montado. Sin embargo, para poder mostrar cualquier interfaz de usuario (UI), el marco debe iniciarse y el marco requiere que /data
se ejecute. Para resolver este problema, se monta un sistema de archivos temporal en /data
, lo que permite a Android solicitar contraseñas, mostrar el progreso o sugerir un borrado de datos según sea necesario. Esto impone la limitación de que para cambiar del sistema de archivos temporal al verdadero sistema de archivos /data
, el sistema debe detener todos los procesos con archivos abiertos en el sistema de archivos temporal y reiniciar esos procesos en el verdadero sistema de archivos /data
. Para ello, todos los servicios deben estar en uno de los tres grupos: core
, main
, ylate_start
.
-
core
: Nunca se apagan después de iniciarse. -
main
: Apagar y reiniciar después de introducir la contraseña del disco. -
late_start
: No se inicia hasta después de que/data
haya sido descifrado y montado.
Para desencadenar estas acciones, la propiedad vold.decrypt
se establece en varias cadenas.Para matar y reiniciar servicios, los comandos init
son:
-
class_reset
: Detiene un servicio pero permite reiniciarlo con class_start. -
class_start
: Reinicia un servicio. -
class_stop
: Detiene un servicio y añade una banderaSVC_DISABLED
. Los servicios detenidos no responden aclass_start
.
Flows
Hay cuatro flujos para un dispositivo encriptado. Un dispositivo se encripta sólo una vez y luego sigue un flujo de arranque normal.
- Encriptar un dispositivo previamente no encriptado:
- Encriptar un nuevo dispositivo con
forceencrypt
: Cifrado obligatorio en el primer arranque (a partir de Android L). - Encriptar un dispositivo existente: Cifrado iniciado por el usuario (Android K y anteriores).
- Encriptar un nuevo dispositivo con
- Encender un dispositivo cifrado:
- Iniciar un dispositivo encriptado sin contraseña: Arrancar un dispositivo encriptado que no tiene contraseña establecida (relevante para dispositivos con Android 5.0 y posterior).
- Inicio de un dispositivo encriptado con contraseña: Inicio de un dispositivo encriptado que tiene una contraseña establecida.
Además de estos flujos, el dispositivo también puede fallar en el cifrado /data
.Cada uno de los flujos se explican en detalle a continuación.
Encriptar un nuevo dispositivo con forceencrypt
Este es el primer arranque normal para un Android 5.0 dispositivo.
- Detectar el sistema de archivos sin cifrar con
forceencrypt
flag/data
no está cifrado pero necesita serlo porqueforceencrypt
lo ordena.Desmontar/data
. - Iniciar el cifrado de
/data
vold.decrypt = "trigger_encryption"
desencadenainit.rc
, lo que hará quevold
cifre/data
sin contraseña.(No se establece ninguna porque debe ser un dispositivo nuevo.) - Montar tmpfs
vold
monta un tmpfs/data
(usando las opciones de tmpfs dero.crypto.tmpfs_options
) y establece la propiedadvold.encrypt_progress
a 0.vold
prepara el tmpfs/data
para arrancar un sistema cifrado y establece la propiedadvold.decrypt
a:trigger_restart_min_framework
- Hacer aparecer el marco para mostrar el progreso
Debido a que el dispositivo prácticamente no tiene datos que cifrar, la barra de progreso a menudo no aparecerá realmente porque el cifrado se produce muy rápidamente. VerEncrypt an existing device para másdetalles sobre el progreso UI.
- Cuando
/data
está encriptado, bajar el marcovold
establecevold.decrypt
atrigger_default_encryption
que inicia eldefaultcrypto
servicio. (Esto inicia el flujo de abajo para montar los datos de usuario encriptados por defecto).trigger_default_encryption
comprueba 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 ninguna contraseña establecida; por lo tanto, desciframos y montamos/data
. - Monte
/data
init
entonces monta/data
en un disco RAM tmpfs usando los parámetros que recoge dero.crypto.tmpfs_options
, que se establece eninit.rc
. - Inicia el framework
Configura
vold
entrigger_restart_framework
, que continúa el proceso de arranque habitual.
Encriptar un dispositivo existente
Esto es lo que ocurre cuando se encripta un dispositivo Android K o anterior no encriptado que ha sido migrado a L.
Este proceso es iniciado por el usuario y se denomina «inplace encryption» 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 terminar el proceso de cifrado.
Atención: Si el dispositivo se queda sin energía y se apaga antes de que haya terminado de encriptarse, los datos de los archivos quedan en un estado parcialmente encriptado. El dispositivo debe ser restablecido de fábrica y todos los datos se pierden.
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 criptográfico. 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: Establece ro.crypto.state = "unencrypted"
y ejecuta el trigger on nonencrypted
init
para continuar el arranque.
- Comprobar contraseña
La UI llama a
vold
con el comandocryptfs enablecrypto inplace
dondepasswd
es la contraseña de la pantalla de bloqueo del usuario. - Retirar el framework
vold
comprueba si hay errores, devuelve -1 si no puede cifrar, e imprime una razón en el log. Si puede cifrar, establece la propiedadvold.decrypt
atrigger_shutdown_framework
. Esto hace queinit.rc
detenga los servicios de las claseslate_start
ymain
. - Crea un pie de página crypto
- Crea un archivo de migas de pan
- Reinicia
- Detecta el archivo de migas de pan
- Comienza a encriptar
/data
vold
y luego establece el mapeo crypto, que crea un dispositivo de bloque criptográfico virtual que se mapea en el dispositivo de bloque real pero encripta cada sector cuando se escribe, y desencripta cada sector cuando se lee.vold
luego crea y escribe los metadatos criptográficos. - Mientras se encripta, mount tmpfs
vold
monta un tmpfs/data
(usando las opciones de tmpfs dero.crypto.tmpfs_options
) y establece la propiedadvold.encrypt_progress
a 0.vold
prepara el tmpfs/data
para arrancar un sistema encriptado y establece la propiedadvold.decrypt
a:trigger_restart_min_framework
- Trae el framework para mostrar el progreso
trigger_restart_min_framework
hace queinit.rc
inicie la clase de serviciosmain
. Cuando el marco ve quevold.encrypt_progress
se establece en 0, trae la barra de progresoUI, 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
se encripta, actualiza el pie de página cryptoCuando
/data
se encripta con éxito,vold
borra la banderaENCRYPTION_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 alguna razón,
vold
establece la propiedadvold.encrypt_progress
enerror_reboot_failed
y la UI debe mostrar un mensaje pidiendo al usuario que pulse un botón para reiniciar. No se espera que esto ocurra nunca.
Inicio de un dispositivo encriptado con encriptación por defecto
Esto es lo que ocurre cuando se arranca un dispositivo encriptado sin contraseña.Debido a que los dispositivos Android 5.0 están encriptados en el primer arranque, no debería haber ninguna contraseña establecida y por lo tanto este es el estado de encriptación por defecto.
- Detectar
/data
encriptado sin contraseñaDetecta que el dispositivo Android está encriptado porque
/data
no se puede montar y uno de los indicadoresencryptable
oforceencrypt
está establecido.vold
establecevold.decrypt
atrigger_default_encryption
, que inicia el serviciodefaultcrypto
.trigger_default_encryption
comprueba el tipo de cifrado para ver si/data
está cifrado con o sin contraseña. - Descifra /datos
Crea el dispositivo
dm-crypt
sobre el dispositivo de bloque para que el dispositivo esté listo para su uso. - Monta /datos
vold
luego monta la partición real/data
descifrada y luego prepara la nueva partición. Establece la propiedadvold.post_fs_data_done
a 0 y luego establecevold.decrypt
atrigger_post_fs_data
. Esto hace queinit.rc
ejecute sus comandospost-fs-data
. Crearán los directorios o enlaces necesarios y luego pondránvold.post_fs_data_done
a 1.Una vez que
vold
ve el 1 en esa propiedad, pone la propiedadvold.decrypt
a:trigger_restart_framework.
Esto hace queinit.rc
inicie los servicios de la clasemain
de nuevo y también inicie los servicios de la claselate_start
por primera vez desde el arranque. - Iniciar framework
Ahora el framework arranca todos sus servicios usando el
/data
descifrado, y el sistema está listo para su uso.
Iniciar un dispositivo encriptado sin encriptación por defecto
Esto es lo que ocurre cuando se arranca 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.
- Detectar dispositivo encriptado con contraseña
Detecta que el dispositivo Android está encriptado porque la bandera
ro.crypto.state = "encrypted"
vold
establecevold.decrypt
atrigger_restart_min_framework
porque/data
estáencriptado con una contraseña. - Montar tmpfs
init
establece cinco propiedades para guardar las opciones de montaje inicialesdadas para/data
con parámetros pasados desdeinit.rc
.vold
utiliza estas propiedades para configurar el mapeo criptográfico:-
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 ASCII de 8 dígitos precedido por 0x)
-
- Inicia el framework para solicitar la contraseña
El framework se inicia y ve que
vold.decrypt
está configurado entrigger_restart_min_framework
. Esto le dice al framework que está arrancando en un disco tmpfs/data
y que necesita obtener la contraseña del usuario.Sin embargo, primero necesita asegurarse de que el disco fue correctamente encriptado. Envía el comando
cryptfs cryptocomplete
avold
.vold
devuelve 0 si el cifrado se completó con éxito, -1 en caso de error interno, o-2 si el cifrado no se completó con éxito.vold
determina esto buscando en los metadatos de encriptación la banderaCRYPTO_ENCRYPTION_IN_PROGRESS
. Si se establece, el proceso de cifrado se interrumpió, y hay datos nousable en el dispositivo. Sivold
devuelve un error, la interfaz de usuario debería mostrar un mensaje al usuario para que reinicie y restablezca de fábrica el dispositivo, y darle un botón para que lo haga. - Desencriptar datos con contraseña
Una vez que
cryptfs cryptocomplete
tiene éxito, el marco de trabajo muestra una interfaz de usuario pidiendo la contraseña del disco. La interfaz de usuario comprueba la contraseña enviando el comandocryptfs checkpw
avold
. Si la contraseña es correcta (lo que se determina montando con éxito el/data
descifrado en una ubicación temporal, y luego desmontándolo),vold
guarda el nombre del dispositivo de bloque descifrado en la propiedadro.crypto.fs_crypto_blkdev
y devuelve el estado 0 a la UI. Si la contraseña es incorrecta, devuelve -1 a la UI. - Stop framework
La UI pone un gráfico de arranque criptográfico y luego llama a
vold
con el comandocryptfs restart
.vold
establece la propiedadvold.decrypt
atrigger_reset_main
, lo que hace queinit.rc
hagaclass_reset main
. Esto detiene todos los servicios de la clase principal, lo que permite desmontar el tmpfs/data
. - Montar
/data
vold
entonces monta la partición real/data
descifrada y prepara la nueva partición (que puede que nunca haya sido preparada si fue cifrada con la opción wipe, que no está soportada en la primera versión). Establece la propiedadvold.post_fs_data_done
a 0 y establecevold.decrypt
atrigger_post_fs_data
. Esto hace queinit.rc
ejecute sus comandospost-fs-data
. Crearán los directorios o enlaces necesarios y luego pondránvold.post_fs_data_done
a 1. Una vez quevold
ve el 1 en esa propiedad, establece la propiedadvold.decrypt
atrigger_restart_framework
. Esto hace queinit.rc
inicie de nuevo los servicios de la clasemain
y también inicie los servicios de la claselate_start
por primera vez desde el arranque. - Iniciar todo el framework
Ahora el framework arranca todos sus servicios utilizando el sistema de archivos
/data
descifrado, y el sistema está listo para su uso.
Fallo
Un dispositivo que falla al descifrar puede estar mal por algunas razones. El dispositivo comienza con la serie normal de pasos para arrancar:
- Detectar el dispositivo cifrado con una contraseña
- Montar tmpfs
- Iniciar el marco para solicitar la contraseña
Pero después de que el marco se abre, el dispositivo puede encontrar algunos errores:
- La contraseña coincide pero no puede descifrar los datos
- El usuario introduce una contraseña incorrecta 30 veces
Si estos errores no se resuelven, solicita al usuario que realice un borrado de fábrica:
Si vold
detecta un error durante el proceso de cifrado, y si aún no se ha destruido ningún dato y el marco está en funcionamiento, vold
establece la propiedad vold.encrypt_progress
en error_not_encrypted
.La interfaz de usuario pide al usuario que se reinicie y le avisa de que el proceso de cifrado no se ha iniciado. Si el error se produce después de que el marco se ha derribado, pero antes de que la barra de progreso UI es para arriba, vold
se reiniciará el sistema. Si el reinicio falla, establece vold.encrypt_progress
enerror_shutting_down
y devuelve -1; pero no habrá nada para capturar el error. Esto no se espera que suceda.
Si vold
detecta un error durante el proceso de cifrado, establece vold.encrypt_progress
a error_partially_encrypted
y devuelve -1. La interfaz de usuario debería entonces mostrar un mensaje diciendo que la encriptación falló y proporcionar un botón para que el usuario restablezca de fábrica el dispositivo.
Almacenamiento de la clave encriptada
La clave encriptada se almacena en los metadatos crypto. El respaldo del hardware se implementa utilizando la capacidad de firma de Trusted Execution Environment (TEE).Anteriormente, ciframos 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, ampliamos este algoritmo firmando la clave resultante con una clave TEE almacenada. La firma resultante se convierte en una clave de longitud adecuada mediante una aplicación más de scrypt. Esta clave se utiliza entonces para cifrar y descifrar la clave maestra. Para almacenar esta clave:
- Genera una clave de cifrado de disco (DEK) aleatoria de 16 bytes y una sal de 16 bytes.
- Aplicar scrypt a la contraseña de usuario y a la sal para producir la clave intermedia 1 de 32 bytes (IK1).
- Acoplar IK1 con cero bytes al tamaño de la clave privada ligada al hardware (HBK).Específicamente, acolchamos como: 00 || IK1 || 00..00; un byte cero, 32 bytes IK1, 223 bytes cero.
- Señalamos el IK1 rellenado con HBK para producir el IK2 de 256 bytes.
- Aplique scrypt a IK2 y sal (la misma sal del paso 2) para producir IK3 de 32 bytes.
- Utilizar los primeros 16 bytes de IK3 como KEK y los últimos 16 bytes como IV.
- Encriptar el DEK con AES_CBC, con la clave KEK, y el vector de inicialización IV.
Cambiar la contraseña
Cuando un usuario decide cambiar o eliminar su contraseña en la configuración, la UI envía el comando cryptfs changepw
a vold
, yvold
vuelve a encriptar la clave maestra del disco con la nueva contraseña.
Propiedades de cifrado
vold
y init
se comunican entre sí mediante el establecimiento de propiedades. Esta es una lista de las propiedades disponibles para el cifrado.
Propiedades de cifrado
Propiedad | Descripción |
---|---|
vold.decrypt trigger_encryption |
Cifrar la unidad sin contraseña. |
vold.decrypt trigger_default_encryption |
Comprueba la unidad para ver si está encriptada sin contraseña.Si lo está, desencripta y móntala,si no, pon vold.decrypt a trigger_restart_min_framework. |
vold.decrypt trigger_reset_main |
Set by vold to shutdown the UI asking for the disk password. |
vold.decrypt trigger_post_fs_data |
Set by vold to prep /data with necessary directories, et al. |
vold.decrypt trigger_restart_framework |
Set by vold to start the real framework and all services. |
vold.decrypt trigger_shutdown_framework |
Set by vold to shutdown the full framework to start encryption. |
vold.decrypt trigger_restart_min_framework |
Establecido por vold para iniciar la barra de progreso UI para el cifrado o solicitar la contraseña, dependiendo del valor de ro.crypto.state . |
vold.encrypt_progress |
Cuando el marco se inicia, si esta propiedad está establecida, entra en el modo de barra de progreso UI. |
vold.encrypt_progress 0 to 100 |
La barra de progreso UI debe mostrar el valor del porcentaje establecido. |
vold.encrypt_progress error_partially_encrypted |
La interfaz de usuario de la barra de progreso debe mostrar un mensaje que indique que el cifrado ha fallado y dar al usuario una opción para reiniciar el dispositivo. |
vold.encrypt_progress error_reboot_failed |
La interfaz de usuario de la barra de progreso debe mostrar un mensaje que indique que el cifrado se ha completado y dar al usuario un botón para reiniciar el dispositivo. No se espera que se produzca este error. |
vold.encrypt_progress error_not_encrypted |
La interfaz de usuario de la barra de progreso debería mostrar un mensaje diciendo que se ha producido un error, que no se ha cifrado ni se han perdido datos, y dar al usuario 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 que responda a este error. Y nunca debería ocurrir de todos modos. |
vold.post_fs_data_done 0 |
Configurado por vold justo antes de configurar vold.decrypt a trigger_post_fs_data . |
vold.post_fs_data_done 1 |
Configurado 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 |
Fijada por el comando vold checkpw para su posterior uso por el comando vold restart . |
ro.crypto.state unencrypted |
Configurado por init para decir que este sistema está funcionando con un /data ro.crypto.state encrypted sin cifrar. Establecido por init para decir que este sistema se está ejecutando con un /data cifrado. |
|
Estas cinco propiedades son establecidas por init cuando intenta montar /data con parámetros pasados desde init.rc . vold las utiliza para configurar el mapeo criptográfico. |
ro.crypto.tmpfs_options |
Establecidas por init.rc con las opciones que init debe utilizar al montar el sistema de archivos tmpfs /data . |