Cito el manual de Android aquí pero..:
NOTA:
La fuente que he utilizado no es directamente relevante para Marshmallow pero sí para Lollipop y superiores.
TL:DR
Me limitaré a responder a las preguntas del candidato. Los detalles técnicos vendrán después.
-
La clave de cifrado por defecto proviene de una fuente de hardware (un chip similar a un TPM) y la contraseña por defecto de AOSP definida como default_password
en el cryptfs.c
archivo de origen, véase más abajo.
-
Sí, no sólo la predeterminada, sino que cualquier contraseña se convierte en una clave y se almacena en un chip similar al TPM, llamado TEE (abreviatura de "Trusted Execution Environment", véase más abajo para más detalles).
-
Un hacker con acceso UART/JTAG a los chips del SoC del dispositivo podría acceder técnicamente a la clave TEE, o un kernel personalizado puede filtrar esta información a un hacker. Algunas agencias de tres letras en las teorías de la conspiración pueden posiblemente asociarse con el OEM para conseguir que estos kernels inseguros se utilicen en dispositivos de producción, pero yo no pondría muchas tiendas por ello. Una vez más, consulte la última sección de esta respuesta para obtener más detalles.
Lo único que impide a un pirata informático acceder a la clave es el enorme esfuerzo que se requiere para hacerlo.
- Comprobación del hash (suma de comprobación) del firmware (llamado "Bota verificada" de Google) se realiza, de hecho, en Lollipop y superiores por defecto (y está disponible a partir de JellyBean 4.3), mediante un módulo del kernel llamado
dm-verity
. Sin embargo, esto es independiente del estado de encriptación.
Fuente: Guía de seguridad de AOSP aquí .
- Sobre el proceso de descifrado del sistema con una contraseña personalizada, véase más abajo. Sólo te diré aquí que la contraseña del usuario está involucrada tanto en la creación como en el uso de la clave de cifrado.
Resumen
Al arrancar por primera vez, el dispositivo crea una clave maestra de 128 bits generada aleatoriamente y luego la convierte en un hash con una contraseña predeterminada 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 proyecto de código abierto de Android cryptfs.c archivo.
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/contraseña del usuario NO provocan la recodificación de la partición de datos del usuario).
Iniciar un dispositivo encriptado con encriptación por defecto
Esto es lo que ocurre cuando se arranca un dispositivo encriptado sin contraseña. Dado que los dispositivos Android 5.0 se cifran en el primer arranque, no debería haber ninguna contraseña establecida y, por tanto, este es el estado de cifrado por defecto.
- Detectar los /datos encriptados sin contraseña
Detectar que el dispositivo Android está encriptado porque /data no se puede montar y una de las banderas encryptable
o forceencrypt
está ajustado.
vold
establece vold.decrypt
a trigger_default_encryption
que inicia el defaultcrypto
servicio. trigger_default_encryption
comprueba el tipo de cifrado para ver si /data está cifrado con o sin contraseña.
- Descifrar /datos
Crea el dm-crypt
sobre el dispositivo de bloque para que el dispositivo esté listo para su uso.
- Montar /data
vold
entonces monta la partición real /data descifrada y luego prepara la nueva partición. Establece la propiedad vold.post_fs_data_done
a 0
y luego establece vold.decrypt
a trigger_post_fs_data
. Esto hace que init.rc
para ejecutar su post-fs-data
comandos. Crearán los directorios o enlaces necesarios y luego establecerán vold.post_fs_data_done
a 1
.
Una vez vold
ve el 1 en esa propiedad, establece la propiedad vold.decrypt
a: trigger_restart_framework
. Esto hace que init.rc
para iniciar los servicios en clase main
de nuevo y también iniciar los servicios en la clase late_start por primera vez desde el arranque.
- Marco de inicio
Ahora el framework arranca todos sus servicios utilizando 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 arrancas 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 el dispositivo encriptado con una contraseña
Detectar que el dispositivo Android está encriptado porque la bandera ro.crypto.state = "encrypted"
vold
establece vold.decrypt
a trigger_restart_min_framework
porque /data está encriptado con una contraseña.
- Montar tmpfs
init
establece cinco propiedades para guardar las opciones de montaje iniciales dadas para /data con parámetros pasados desde init.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)
- Iniciar el marco para solicitar la contraseña
El marco se pone en marcha y ve que vold.decrypt
se ajusta a trigger_restart_min_framework
. Esto indica al framework que está arrancando en un tmpfs /data
disco y necesita obtener la contraseña del usuario.
Sin embargo, primero tiene que asegurarse de que el disco está bien encriptado. Para ello, envía el comando cryptfs cryptocomplete
a vold
. vold
devuelve 0 si la encriptación se completó con éxito, -1 en caso de error interno, o -2 si la encriptación no se completó con éxito. vold
lo determina buscando en los metadatos criptográficos del CRYPTO_ENCRYPTION_IN_PROGRESS
bandera. Si se establece, el proceso de encriptación 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 el dispositivo, y darle al usuario un botón para que lo pulse.
- Descifrar datos con contraseña
Una vez cryptfs cryptocomplete
tiene éxito, el marco muestra una interfaz de usuario que pide la contraseña del disco. La UI comprueba la contraseña enviando el comando cryptfs checkpw
a vold
. Si la contraseña es correcta (lo que se determina al montar con éxito el /data
en una ubicación temporal y luego lo desmonta), vold guarda el nombre del dispositivo de bloque descifrado en la propiedad ro.crypto.fs_crypto_blkdev
y devuelve el estado 0 a la UI. Si la contraseña es incorrecta, devuelve -1 a la UI.
- Marco de parada
La interfaz de usuario pone un gráfico de arranque criptográfico y luego llama a vold con el comando cryptfs restart
. vold
establece la propiedad vold.decrypt
a trigger_reset_main
, lo que provoca init.rc
para hacer class_reset main
. Esto detiene todos los servicios en el main
que permite a la clase tmpfs /data
para ser desmontado.
- Montar /data
vold
y luego monta el real descifrado /data
y prepara la nueva partición (que puede no haber sido preparada nunca si se cifró con la opción de borrado, que no está soportada en la primera versión). Establece la propiedad vold.post_fs_data_done
a 0
y luego establece vold.decrypt
a trigger_post_fs_data
. Esto hace que init.rc
para ejecutar su post-fs-data commands
. Crearán los directorios o enlaces necesarios y luego establecerán vold.post_fs_data_done
a 1
. Una vez que vold
ve el 1
en esa propiedad, establece la propiedad vold.decrypt
a trigger_restart_framework
. Esto hace que init.rc
para iniciar los servicios en clase main
de nuevo y también iniciar los servicios en clase late_start
por primera vez desde el arranque.
- Iniciar el marco completo
Ahora el framework arranca todos sus servicios utilizando el sistema de archivos /data descifrado, y el sistema está listo para ser utilizado.
Almacenamiento de la clave cifrada
La clave cifrada se almacena en los metadatos criptográficos. 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 entonces en una clave de longitud adecuada mediante una aplicación más de scrypt
. Esta clave se utiliza para cifrar y descifrar la clave maestra. Para almacenar esta clave:
- Generar una clave de cifrado de disco (DEK) aleatoria de 16 bytes y una sal de 16 bytes.
- Aplique
scrypt
a la contraseña del usuario y la sal para producir la clave intermedia 1 (IK1) de 32 bytes.
- Rellena IK1 con cero bytes hasta el tamaño de la clave privada ligada al hardware (HBK). En concreto, rellenamos como: 00 || IK1 || 00..00; un byte cero, 32 bytes IK1, 223 bytes cero.
- Firma rellena IK1 con HBK para producir IK2 de 256 bytes.
- Aplique
scrypt
a IK2 y sal (la misma sal del paso 2) para producir IK3 de 32 bytes.
- Utilice los primeros 16 bytes de IK3 como KEK y los últimos 16 bytes como IV.
- Cifrar DEK con AES_CBC, con clave KEK, y vector de inicialización IV.
0 votos
Gracias. Aunque se aplique a Lollipop esta es la respuesta correcta hasta donde yo sé. Pensaba que había una diferencia entre M y L porque no recuerdo haber podido configurar el cifrado sin contraseña en L, ni haber podido eliminar mi PIN después del cifrado.