Generador aleatorio: mejoras en Linux!

Publicado por Diego Córdoba en

Hoy les comentaré algunos detalles del nuevo generador aleatorio de números, o random generator, del kernel Linux en su v5.17, base de muchos mecanismos criptográficos.

El generador aleatorio de Linux, conocido por hacer uso de dispositivos como /dev/random o /dev/urandom, se utiliza con frecuencia en la generación de claves criptográficas, y en mecanismos de intercambio de claves de un único uso para el establecimiento de comunicaciones seguras.

Anteriormente ya hablé sobre generadores aleatorios y entropía, temas que voy a comentar en este post también… para ampliar algunos detalles de este artículo pueden pasarse por: Entropía: su uso en los generadores aleatorios.
En ese artículo van a encontrar también un video que grabé al respecto para el canal de youtube de JuncoTIC 🙂

¡Empecemos!

Números «realmente» aleatorios

random Generador aleatorio entropia
Generador /dev/random

La generación de números aleatorios por software no es una tarea simple. Si se ejecuta el mismo código varias veces, y se utiliza la misma entrada o semilla, el resultado será siempre el mismo. De esta manera, si un programa hace uso de un generador aleatorio que use siempre la misma semilla, producirá valores aleatorios predecibles. Así, un atacante podría, predecir la salida del software para una entrada determinada, realizar ingeniería inversa y detallar el funcionamiento interno de la aplicación. De esta manera podría romper, por ejemplo, algunos mecanismos criptográficos, como ocurrió con el generador aleatorio de Windows 2000.

Una forma de evitar esta predicción de resultados es utilizar, como semilla del generador, datos realmente aleatorios externos al sistema. Esto puede lograrse leyendo los movimientos del ratón, actividad del teclado, y la temporización de actividades de E/S a disco o de la actividad de la red. Esto en ciencias de la computación se denomina «entropía«. El núcleo Linux mantiene un pool de entropía como fuente para los generadores aleatorios.

En Linux los generadores aleatorios utilizan este pool de entropía como semilla, de modo que, cuando el pool se haya consumido, los generadores comenzarán a emitir valores predecibles.

/dev/random y /dev/urandom

Linux dispone de dos dispositivos generadores de valores aleatorios: /dev/random y /dev/urandom.

  • /dev/random retorna valores aleatorios desde el pool de entropía. Si el nivel de entropía del pool no es suficiente para garantizar cierta aleatoriedad, el dispositivo se bloqueará. Esto puede generar esperas en las aplicaciones hasta que el nivel de entropía sea el adecuado.
  • /dev/urandom nunca se bloqueará y retornará un valor aleatorio cuando se le pida. Al no evaluar la entropía del sistema, este dispositivo generará valores aleatorios de manera rápida y práctica. Como desventaja puede que dichos valores no posean buena calidad aleatoria.

En fin, el programador que desee utilizar los generadores aleatorios de Linux debe decidir entre obtener números aleatorios más puros desde /dev/random, con los posibles retrasos generados por el pool de entropía, o hacerlo desde /dev/urandom, con la posible pérdida de aleatoriedad de los valores.

En general, la recomendación siempre es usar /dev/urandom para la generación aleatoria, y debería bastar para prácticamente cualquier aplicación.

Otra opción sería utilizar generadores aleatorios por hardware (HWRNG), pero incluso estos generadores tienen problemas.

Mejoras del generador aleatorio de Linux

Desde la v4.8 del kernel, /dev/urandom mejoró su «aleatoriedad» al incorporar el algoritmo ChaCha20, logrando mejorar su resistencia a la predicción.

El kernel v5.6 en 2020 incorporó mejoras en el dispositivo /dev/random, que permitieron que se bloquee únicamente al momento de inicializar el dispositivo, no durante su uso. De esta manera no se producen retrasos de procesamiento ni bloqueos al obtener valores aleatorios de ninguno de los dos dispositivos.

La v5.17 eliminó definitivamente el uso del algoritmos hash SHA-1, que fue vulnerado en 2005. Este algoritmo se ha ido reemplazando gradualmente desde hace años. Ahora fue reemplazado definitivamente por un algoritmo derivado de ChaCha20: BLAKE2.

Generador aleatorio y virtualización

Un problema interesante es el que se presenta en máquinas virtuales duplicadas. Como los generadores aleatorios obtienen la secuencia de números a partir del pool de entropía, al clonar una máquina virtual también se clonará el pool de entropía. Esta duplicación incluye el estado interno del sistema, por lo que ambas generarán la misma secuencia de números aleatorios. Esto será al menos por un tiempo, el suficiente para que los pools de entropía se «regeneren».

Generador aleatorio virt-manager

Y esto no afecta solamente a un sistema virtual duplicado. Si el sistema de virtualización genera un checkpoint en un instante determinado, al momento de restaurar el sistema y volver a ese checkpoint se estará restaurando el estado interno del sistema en ese momento. Esta restauración incluye el pool de entropía, por lo que el generador aleatorio producirá los mismos números random que se generaron en aquella oportunidad. De nuevo, esto se producirá hasta que el pool de entropía se perturbe con ruido.

Una solución propuesta…

La solución para estos casos fue el agregado de un identificador de máquina virtual, o VMID (Virtual-Machine ID) en el firmware de ACPI. Cuando una máquina virtual se duplica o se restaura a un checkpoint, este identificador cambiará, por lo que el kernel podrá leerlo. Esto le permitirá detectar la situación y llevar a cabo las acciones necesarias para actualizar el pool de entropía.

Un parche propuesto por Jason Donenfeld añade un controlador nuevo, «vmgenid», que pone el VMID del firmware ACPI a disposición del kernel. De esta manea vmgenid notificará al kernel de un cambio en el identificador de máquina virtual, y éste llamará a una función especial, crng_vm_fork_inject(), que informará al generador aleatorio que debe «regenerar» el pool de entropía.

Donenfeld también se encuentra desarrollando la manera en la que las notificaciones de cambio de ID de máquina virtual sean reenviadas a otros subsistemas del núcleo. Un dato de color: WireGuard VPN fue el primer usuario interesado en estas actualizaciones. Cuando una máquina virtual se clona es importante limpiar las sesiones VPN, evitando cifrar los mensajes en texto plano usando las mismas claves y nonce.

Conclusiones

La versión 5.17 del kernel Linux ha comenzado a incorporar cambios en el generador aleatorio, los dispositivos /dev/random y /dev/urandom realizan ya la misma operación de obtención de números aleatorios, tal y como ocurre en otros sistemas *nix como FreeBSD y macOS.

La siguiente versión, 5.18, continuará añadiendo mejoras al respecto, de hecho Donenfeld intenta introducir sus mejoras en la versión 5.18 de Linux. Puede leerse un detalle de su propuesta acá.

¡Espero que el artículo les resulte interesante!

¡Me despido hasta la próxima! (no sin antes dejar un poquito de humor relacionado :P)


¿Preguntas? ¿Comentarios?

Si tenés dudas, o querés dejarnos tus comentarios y consultas, sumate al grupo de Telegram de la comunidad JuncoTIC!
¡Te esperamos!


Diego Córdoba

- Ingeniero en Informática - Mg. Teleinformática - Tesis pendiente - Docente universitario - Investigador