Google se compromete a impulsar la igualdad racial para las comunidades afrodescendientes. Obtén información al respecto.

Llaves envueltas en hardware

Como la mayoría de los programas de cifrado de archivos y discos, el cifrado de almacenamiento de Android se basa tradicionalmente en que las claves de cifrado sin procesar estén presentes en la memoria del sistema para que se pueda realizar el cifrado. Incluso cuando el cifrado se realiza mediante hardware dedicado en lugar de software, el software generalmente todavía necesita administrar las claves de cifrado sin procesar.

Tradicionalmente, esto no se ve como un problema porque las claves no estarán presentes durante un ataque fuera de línea, que es el principal tipo de ataque contra el que se pretende proteger el cifrado de almacenamiento. Sin embargo, hay un deseo de proporcionar una mayor protección contra otros tipos de ataques, como el ataque de arranque en frío , y los ataques en línea, donde un atacante podría ser capaz de perder memoria del sistema sin comprometer completamente el dispositivo.

Para resolver este problema, Android 11 introdujo la compatibilidad con teclas de hardware envuelto, en donde el soporte de hardware está presente. Las claves envueltas en hardware son claves de almacenamiento que solo el hardware dedicado conoce en forma bruta; el software solo ve y funciona con estas claves en formato envuelto (encriptado). Este hardware debe ser capaz de generar e importar claves de almacenamiento, empaquetar claves de almacenamiento en formas efímeras y de largo plazo, derivar subclaves, programar directamente una subclave en un motor de cifrado en línea y devolver una subclave separada al software.

Nota: un motor en línea de cifrado (o hardware de cifrado inline) se refiere a hardware que cifra / descifra los datos mientras que está en su camino hacia / desde el dispositivo de almacenamiento. Por lo general, este es un controlador de host UFS o eMMC que implementa las extensiones criptográficas definidas por la especificación JEDEC correspondiente.

Diseño

Esta sección presenta el diseño de la función de teclas envueltas en hardware, incluido el soporte de hardware que se requiere para ello. Esta discusión se centra en el cifrado de archivos (FBE), pero la solución se aplica a la encriptación de metadatos también.

Una forma de evitar la necesidad de las claves de cifrado sin procesar en la memoria del sistema sería mantenerlas solo en las ranuras de claves de un motor de cifrado en línea. Sin embargo, este enfoque tiene algunos problemas:

  • La cantidad de claves de cifrado puede exceder la cantidad de ranuras de claves.
  • Los motores de cifrado en línea solo se pueden utilizar para cifrar / descifrar bloques completos de datos en el disco. Sin embargo, en el caso de FBE, el software aún necesita poder realizar otro trabajo criptográfico, como el cifrado de nombres de archivos y la obtención de identificadores de claves. El software aún necesitaría acceso a las claves FBE sin procesar para realizar este otro trabajo.

Para evitar estos problemas, las claves de almacenamiento en cambio se convierten en teclas de hardware envuelto, que sólo puede ser sin envolver y utilizados por hardware dedicado. Esto permite admitir un número ilimitado de claves. Además, la jerarquía de claves se modifica y se traslada parcialmente a este hardware, lo que permite devolver una subclave al software para tareas que no pueden utilizar un motor de cifrado en línea.

Jerarquía de claves

Keys se pueden derivar de otras claves utilizando una (función de derivación de claves) KDF como HKDF , resultando en una jerarquía de claves.

El siguiente diagrama representa una jerarquía de claves típico para FBE cuando no se utilizan las teclas de hardware envuelto:

Jerarquía de claves FBE (estándar)
Figura 1. jerarquía de claves FBE (estándar)

La clave de clase FBE es la clave de cifrado sin procesar que Android pasa al kernel de Linux para desbloquear un conjunto particular de directorios cifrados, como el almacenamiento cifrado con credenciales para un usuario de Android en particular. (En el núcleo, esta clave se llama una llave maestra fscrypt.) De esta tecla, el núcleo deriva las siguientes subclaves:

  • El identificador de clave. No se utiliza para el cifrado, sino que es un valor que se utiliza para identificar la clave con la que se protege un archivo o directorio en particular.
  • La clave de cifrado del contenido del archivo
  • La clave de cifrado de nombres de archivo

Por el contrario, el siguiente diagrama muestra la jerarquía de claves para FBE cuando se utilizan claves envueltas en hardware:

Jerarquía de claves FBE (con clave envuelta en hardware)
Figura jerarquía de claves 2. FBE (con llave de hardware-envuelto)

En comparación con el caso anterior, se ha agregado un nivel adicional a la jerarquía de claves y se ha reubicado la clave de cifrado del contenido del archivo. El nodo raíz todavía representa la clave que Android pasa a Linux para desbloquear un conjunto de directorios encriptados. Sin embargo, ahora esa clave está en forma de empaquetado efímero, y para poder usarse, debe pasarse al hardware dedicado. Este hardware debe implementar dos interfaces que tomen una clave empaquetada de manera efímera:

  • Una interfaz para derivar inline_encryption_key y directamente programarlo en un keyslot del motor de cifrado en línea. Esto permite cifrar / descifrar el contenido del archivo sin que el software tenga acceso a la clave sin formato. En los núcleos comunes para Android, esta interfaz corresponde a la blk_ksm_ll_ops::keyslot_program operación, que deben ser implementadas por el controlador de almacenamiento.
  • Una interfaz para derivar y retorno sw_secret ( "secreto de software" - también llamado el "secreto prima" en algunos lugares), que es la llave que Linux utiliza para derivar las subclaves para todo lo que no sea cifrado contenido del archivo. En los núcleos comunes para Android, esta interfaz corresponde a la blk_ksm_ll_ops::derive_raw_secret operación, que deben ser implementadas por el controlador de almacenamiento.

Para derivar inline_encryption_key y sw_secret de la clave de almacenamiento prima, el hardware debe utilizar un criptográficamente fuerte KDF. Este KDF debe seguir las mejores prácticas de criptografía; debe tener una fuerza de seguridad de al menos 256 bits, es decir, suficiente para cualquier algoritmo que se utilice más adelante. También debe usar una etiqueta distinta, contexto y / o cadena de información específica de la aplicación al derivar cada tipo de subclave para garantizar que las subclaves resultantes estén criptográficamente aisladas, es decir, el conocimiento de una de ellas no revela ninguna otra. No es necesario extender la clave, ya que la clave de almacenamiento sin procesar ya es una clave uniformemente aleatoria.

Técnicamente, se podría utilizar cualquier KDF que cumpla con los requisitos de seguridad. Sin embargo, con fines de prueba, es necesario volver a implementar el mismo KDF en el código de prueba. Actualmente, se ha revisado e implementado un KDF; que se puede encontrar en el código fuente de vts_kernel_encryption_test . Se recomienda que el uso de hardware de este KDF, que utiliza NIST SP 800-108 "KDF en modo contador" con AES-256-CMAC como el PRF. Tenga en cuenta que para ser compatible, todas las partes del algoritmo deben ser idénticas, incluida la elección de contextos KDF y etiquetas para cada subclave.

Envoltura de llaves

Para cumplir los objetivos de seguridad de las claves envueltas en hardware, se definen dos tipos de encapsulado de claves:

  • Envoltura efímera: el hardware cifra la clave cruda usando una clave que se genera aleatoriamente en cada arranque y no está expuesto directamente fuera del hardware.
  • Envolver a largo plazo: el hardware cifra la clave cruda usando una clave única, persistente integrado en el hardware que no está expuesta directamente al exterior del hardware.

Todas las claves que se pasan al kernel de Linux para desbloquear el almacenamiento se empaquetan de manera efímera. Esto garantiza que si un atacante puede extraer una clave en uso de la memoria del sistema, esa clave no solo se podrá usar fuera del dispositivo, sino también en el dispositivo después de reiniciar.

Al mismo tiempo, Android todavía necesita poder almacenar una versión encriptada de las claves en el disco para que puedan desbloquearse en primer lugar. Las claves sin formato funcionarían para este propósito. Sin embargo, es deseable que las claves sin formato nunca estén presentes en la memoria del sistema para que nunca se puedan extraer para usarlas fuera del dispositivo, incluso si se extraen en el momento del arranque. Por este motivo, se define el concepto de envoltura a largo plazo.

Para admitir la administración de claves envueltas en estas dos formas diferentes, el hardware debe implementar las siguientes interfaces:

  • Interfaces para generar e importar claves de almacenamiento, devolviéndolas en formato empaquetado a largo plazo. Estas interfaces se accede indirectamente a través de KeyMint, y corresponden a la TAG_STORAGE_KEY etiqueta KeyMint. La capacidad de "generar" es utilizado por vold para generar nuevas claves de almacenamiento para uso de Android, mientras que la capacidad de "importación" es utilizado por vts_kernel_encryption_test de claves de prueba de importación.
  • Una interfaz para convertir una clave de almacenamiento empaquetada a largo plazo en una clave de almacenamiento empaquetada efímeramente. Esto corresponde a la convertStorageKeyToEphemeral método KeyMint. Este método se utiliza por tanto vold y vts_kernel_encryption_test con el fin de desbloquear el almacenamiento.

El algoritmo de envoltura de claves es un detalle de implementación, pero debe usar un AEAD fuerte como AES-256-GCM con IVs aleatorios.

Se requieren cambios de software

AOSP ya tiene un marco básico para admitir claves envueltas en hardware. Esto incluye el apoyo en los componentes del espacio de usuario como vold , así como el soporte en el núcleo Linux en negro-cripto, fscrypt y clave por defecto dm.

Sin embargo, se requieren algunos cambios específicos de la implementación.

Cambios de KeyMint

KeyMint aplicación del dispositivo debe ser modificado para el apoyo TAG_STORAGE_KEY e implementar el convertStorageKeyToEphemeral método.

En Keymaster, exportKey se utilizó en lugar de convertStorageKeyToEphemeral .

Cambios en el kernel de Linux

El controlador del núcleo de Linux para el motor de cifrado en línea del dispositivo debe ser modificado para establecer BLK_CRYPTO_FEATURE_WRAPPED_KEYS , hacen que el keyslot_program() y keyslot_evict() las operaciones de apoyo a la programación / desalojar las llaves de hardware envuelto, e implementar el derive_raw_secret() operación.

Pruebas

Aunque el cifrado con claves envueltas en hardware es más difícil de probar que el cifrado con claves estándar, aún es posible realizar la prueba importando una clave de prueba y volviendo a implementar la derivación de clave que hace el hardware. Esto se implementa en vts_kernel_encryption_test . Para ejecutar esta prueba, ejecute:

atest -v vts_kernel_encryption_test

Leer el registro de la prueba y verificar que los casos de prueba de hardware clave envueltas (por ejemplo FBEPolicyTest.TestAesInlineCryptOptimizedHwWrappedKeyPolicy y DmDefaultKeyTest.TestHwWrappedKey ) no fueron omitidos debido al apoyo a las teclas de hardware envuelto no ser detectado, ya que los resultados de las pruebas aún se "pasan" de Ese caso.

Habilitar

Una vez que el soporte clave de hardware-envuelta del dispositivo está funcionando correctamente, puede realizar los siguientes cambios en el dispositivo de fstab archivo para hacer uso de Android para FBE y el cifrado de metadatos:

  • FBE: añadir el wrappedkey_v0 bandera al fileencryption parámetro. Por ejemplo, utilice fileencryption=::inlinecrypt_optimized+wrappedkey_v0 . Para más detalles, consulte la documentación de la FBE .
  • Cifrado de metadatos: añadir el wrappedkey_v0 bandera al metadata_encryption parámetro. Por ejemplo, el uso metadata_encryption=:wrappedkey_v0 . Para más detalles, consulte la documentación de cifrado de metadatos .