15 votos

¿Cómo funciona técnicamente el cifrado de Marshmallow?

Acabo de instalar Marshmallow en un Nexus 5 a través de una actualización empujada. Estoy confundido sobre el funcionamiento de la encriptación. Tengo buenos conocimientos técnicos sobre el cifrado en los ordenadores. Me gustaría adquirir conocimientos similares sobre Android 6.

Lo siguiente es lo que hice y cómo me confundí. Después de un restablecimiento de fábrica configuré un PIN y luego encripté el dispositivo. Al arrancar me pidió el PIN, lo cual era de esperar. Luego quité el PIN y reinicié el dispositivo. No me pidió ningún PIN en el arranque pero el dispositivo seguía informando de que estaba encriptado en el menú de configuración. Esto último es lo que me confunde, ya que esperaba que el PIN desbloqueara la clave de descifrado.

Preguntas:

  • En el caso del cifrado sin PIN, ¿de dónde viene la clave de descifrado? Supongo que se almacena en un chip similar a un TPM, ¿es esto correcto? Si es así, ¿qué impide que un hacker solicite esta clave al chip? ¿Comprueba el hash del firmware? ¿Algo más? Los detalles técnicos serían muy apreciados.
  • En el caso de la encriptación con PIN, ¿se utiliza el PIN como un token adicional para acceder a la clave de desencriptación? O el proceso de descifrado funciona exactamente igual que si no hubiera PIN.

Respuesta TL;DL:

La clave de descifrado se desbloquea con todo lo siguiente:

  • El PIN (o contraseña, etc.) o una contraseña por defecto si no hay ninguna
  • Un TEE (un generador de firmas respaldado por hardware que utiliza claves que no pueden ser extraídas)
  • Una sal (de fácil acceso, pero que previene los ataques de las tablas del arco iris)

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.

16voto

Tamoghna Chowdhury Puntos 33

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.

  1. 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.

  2. 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).

  3. 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.

  1. 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í .

  1. 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.

  1. 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.

  1. Descifrar /datos

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

  1. 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.

  1. 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.

  1. 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.

  1. 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)

  1. 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.

  1. 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.

  1. 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.

  1. 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.

  1. 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:

  1. Generar una clave de cifrado de disco (DEK) aleatoria de 16 bytes y una sal de 16 bytes.
  2. Aplique scrypt a la contraseña del usuario y la sal para producir la clave intermedia 1 (IK1) de 32 bytes.
  3. 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.
  4. Firma rellena IK1 con HBK para producir IK2 de 256 bytes.
  5. Aplique scrypt a IK2 y sal (la misma sal del 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. Cifrar DEK con AES_CBC, con clave KEK, y vector de inicialización IV.

0 votos

¿Qué pasa con Android N? Los colegas habían hecho la suposición de que el cifrado es Android 7 es más débil porque el inicio del dispositivo no está protegido como antes y por lo tanto un atacante podría tenerlo más fácil que antes, ¿crees que esto es cierto?

0 votos

@David eso está fuera del alcance de esta pregunta, por favor, pregunta otra sobre Android Nougat.

0 votos

PreguntAndroid.com

PreguntAndroid es una comunidad de usuarios de Android en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X