Sous Linux, on parle d’entropie comme étant la quantité d’information permettant d’alimenter un générateur de nombres pseudo-aléatoires (PRNG).
L’entropie, c’est-ce que c’est ?
Description de l’entropie
L’entropie thermodynamique désigne la quantité de désordre d’un système physique : cette quantité augmente lorsque le système est soumis à une transformation irréversible. Qui dit transformation irréversible dit impossibilité de diminuer l’entropie d’un système.
Le terme entropie de Shannon est également employé en cryptographie, comme étant l’incertitude d’une source de données. Plus la variabilité des données est grande, moins on est capable d’en prédire la suite, et plus l’entropie de Shannon est grande. Ce terme possède quelques analogies avec la thermodynamique. Le noyau Linux utilise également le terme.
Pour différentes opérations, le noyau du système d’exploitation a besoin d’être capable de générer des nombres (ou des données) aléatoires. C’est un pilier fondamental de nombreux algorithmes de cryptographie comme GPG ou SSL par exemple.
Malheureusement, ces nombres aléatoires ne tombent pas du ciel, et le noyau est obligé de recourir à des astuces logicielles pour les produire. Le noyau utilise un amalgame de données variables (état des disques durs, IO, date, saisies clavier, périphériques, …) comme source d’instabilité, ou source d’entropie, de son générateur de nombres aléatoires. Le résultat final est une bonne approche logicielle de l’aléatoire, on parle de PRNG (pseudorandom number generator).
Cette entropie n’est pas illimitée, le noyau ne peut pas générer de grands volumes de données aléatoires sans être à court à un moment ou à un autre : le pool d’entropie se vide au fur et à mesure de son utilisation.
Comment afficher l’entropie ?
Pour interroger le noyau sur la quantité d’entropie qu’il a pu récolter depuis différentes éléments variants, il faut afficher le contenu de
/proc/sys/kernel/random/entropy_avail.
1 2 |
root@ordinateur:~# cat /proc/sys/kernel/random/entropy_avail 3183 |
Le nom de ce fichier signifie « entropie disponible », ce qui montre bien que la source d’entropie du noyau est stockée dans un pool (un réservoir) qui peut se vider si on puise trop fort dedans.
Voici la preuve en exemple en utilisant le périphérique de générateur aléatoire /dev/random .
1 2 3 4 5 6 7 8 |
root@ordinateur:~# cat /proc/sys/kernel/random/entropy_avail 3183 root@paul-desktop:~# dd if=/dev/random of=/dev/null bs=200K count=1 0+1 enregistrements lus 0+1 enregistrements écrits 78 bytes copied, 0,000334657 s, 233 kB/s root@ordinateur:~# cat /proc/sys/kernel/random/entropy_avail 98 |
On a fait diminuer l’entropie du noyau de 3183 à 98. Pour se donner une idée, si votre système tombe sous les 1000, il risque d’avoir des difficultés à générer des nombres aléatoires lorsque cela lui sera demandé. Il va donc attendre paisiblement jusqu’à ce qu’il collecte suffisamment d’entropie.
Qui consomme mon entropie ?
Si le chiffre affiché dans /proc/sys/kernel/random/entropy_avail diminue et tend vers zéro, vous êtes à court d’entropie.
Le périphérique /dev/random , le principal pourvoyeur d’aléatoire du système, va donc faire attendre tous les logiciels qui font appel à lui, le temps que le stock d’entropie se reconstitue. C’est le principal moyen utilisé par les logiciels pour faire débiter le générateur d’octets aléatoires. La plupart du temps, cela n’a aucune incidence sur la stabilité du système ni même sur ses performances, car le périphérique /dev/random devrait normalement être utilisé dans très peu de cas où la sécurité cryptographique est vitale.
L’utilisation du périphérique /dev/urandom restera possible quoi qu’il arrive de par sa nature non-bloquante. L’utilisation de ce périphérique consomme un peu d’entropie.
Le noyau lui-même consomme de l’entropie, car certaines opérations internes sont volontairement aléatoires dans la gestion des processus et du réseau.
Lors de la génération de clés GPG, SSL ou SSH, de l’entropie est consommée. On voit sur la sortie écran ci-dessous que la génération de clés GPG a été ralentie par le manque d’entropie, avec un message dans ce sens.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
root@ordinateur:~# gpg --gen-key gpg (GnuPG) 1.4.20; Copyright (C) 2015 Free Software Foundation, Inc. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. [...] Faut-il modifier le (N)om, le (C)ommentaire, l'(A)dresse électronique ou (O)ui/(Q)uitter ? O Une phrase secrète est nécessaire pour protéger votre clef secrète. De nombreux octets aléatoires doivent être générés. Vous devriez faire autre chose (taper au clavier, déplacer la souris, utiliser les disques) pendant la génération de nombres premiers ; cela donne au générateur de nombres aléatoires une meilleure chance d'obtenir suffisamment d'entropie. Il n'y a pas suffisamment d'octets aléatoires disponibles. Veuillez faire autre chose pour que le système d'exploitation puisse rassembler plus d'entropie (76 octets supplémentaires sont nécessaires). ..+++++ ........+++++ gpg: clef 9A046E40 marquée de confiance ultime. les clefs publique et secrète ont été créées et signées. [...] |
Le serveur SSH consomme également un peu d’entropie, et il peut souffrir de lenteurs lors de l’établissement de connexions si celle-ci vient à manquer.
Les machines virtuelles et l’entropie
Les machines virtuelles sont particulièrement susceptibles d’arriver à court d’entropie car elles tournent dans un environnements logiciel (l’hyperviseur) beaucoup trop pur par rapport à un environnement matériel « bare metal ». Sans avoir accès directement à un disque dur mécanique, une carte son, une saisie clavier, des mouvements de souris, la source d’entropie de la machine virtuelle se trouve très diminuée.
Par exemple, les blocages lors de la génération de clés GPG seront fréquents sur les machines virtuelles.
L’environnement de virtualisation KVM permet d’y relier avec le pilote virtio-rng qui permet de piper un périphérique de l’hôte vers la machine invitée. L’équivalent Xen de virtio-rng sous KVM est xentropyd (merci pTTy en commentaire).
Comment améliorer l’entropie du système ?
Les générateurs matériels de nombre aléatoires
La meilleure méthode pour aider un système d’exploitation à renouveler son entropie disponible, c’est de recourir à un générateur de nombres aléatoires de type matériel.
Il existe un excellent article Wikipédia sur les différents matériels disponibles sur le marché. Je vous propose le contenu de archive.org car Wikipédia a malheureusement supprimé l’article en Août 2018 sous prétexte que les catalogues de produits ne sont pas acceptés sur une encyclopédie en ligne. Pourtant certains matériels listés sont ouverts et potentiellement utiles.
Curieusement, ce type de produit reste très peu répandu. Sun Microsystems en produisait, sinon la plupart des produits plutôt amateurs et réalisés par des petites entreprises d’électronique. A se demander si l’offre du marché n’est pas régulée d’une manière ou d’une autre.
Clés USB les plus populaires
Selon moi, le dispositif BitBabbler est un des meilleurs disponibles, avec une construction électronique qui semble réputée, un matériel entièrement open-source et une capacité de produire entre 650 Kbit/s et 2,5 Mbit/s. Leur site était actif à la date de rédaction de cet article (2017) mais il est malheureusement hors-ligne en 2022.
On parle souvent sur les forums de Simtec et leur Entropy Key compatible Debian, mais leur produit n’est plus disponible à la vente depuis un petit moment.
Pour en citer d’autres : OneRNG, ChaosKey, TrueRNG, …
Toutes ces clés sont accessibles via le périphérique /dev/hwrng. Les noyaux Linux les plus récents (comme le 4.9 utilisé par Debian 9) utiliseront cette source d’entropie naturellement via le processus noyau [hwrng] . Pour les noyaux les moins récents (au moins jusqu’à la version 3.16 utilisée par Debian 8.6) on utilisera rng-tools pour alimenter /dev/random.
Rtl-sdr
Un hacking particulièrement intéressant à ce sujet, c’est de transformer une clé USB qui était à l’origine un tuner TNT basée sur le chipset rtl-sdr, pour générer des données aléatoires provenant du bruit électromagnétique ambiant (jusqu’à 2,8 Mbit/s). On peut s’en procurer une pour une somme modique, mais son inconvénient est de nécessiter une antenne. Il existe un article détaillé sur cette méthode que j’ai moi-même testée avec succès.
Le paquet rtl-entropy nous explique sur sa home page que l’on peut connecter une résistance de 75 ohms sur la prise antenne, et mettre l’ensemble dans une boite métallique qui fait office de cage de faraday. Cette méthode permet de mesurer un bruit thermique, qui est une source physique d’aléatoire d’excellente qualité, impossible à influencer par ondes radio. Il ne manque plus qu’à trouver un fablab qui pourrait vendre ces blindages, et on pourrait alors utiliser ce générateur USB professionnellement à l’intérieur d’un châssis de serveur.
En creusant, on se rend compte que le dispositif rtl-sdr n’égale pas un générateur aléatoire comme le BitBabbler. J’ai d’ailleurs consacré tout un article à ce sujet.
Raspberry pi et son bcm2708
Le Raspberry Pi fait mieux que la plupart de nos ordinateurs et serveurs : il a un chipset matériel qui génère des données aléatoires. Il faut croire que ses concepteurs se doutaient que certaines applications isolées, avec peu de stimuli externes, nécessiteraient une bonne source aléatoire. Voici un article pour l’exploiter.
Intel rdrand
Intel a ajouté à ces processeurs Ivy Bridge une instruction rdrand pour générer des nombres aléatoires. Les performances sont très importantes, jusqu’à 3 Gbit/s.
A l’époque en 2013 cela a provoqué de nombreux questionnements sur la fiabilité de cette instruction, et sa potentielle compromission par la NSA.
Le noyau Linux utilise cette instruction rdrand pour alimenter son générateur de nombres aléatoires, mais il continue à combiner plusieurs sources, ce qui garantit normalement que le noyau ne souffrira pas de failles dues à une seule de ces sources. A toutes les personnes réticentes, Linus Torvalds a exprimé à ce sujet « We actually know what we are doing. You don’t« . Ce sujet conflictuel a été la cause du départ du mainteneur du RNG Linux. Le bon sens nous pousse à croire que le mélange de différentes sources d’entropie est préférable, même si l’une d’entre elle est compromise. En réalité les sources d’entropie faibles sont dangereuses, même si utilisées parmi d’autres (source).
Il y aurait apparemment eu des pressions sur le noyau Linux pour utiliser rdrand comme seule et unique source d’entropie du noyau (source), ce qui serait mauvais du point de vue sécuritaire. Imaginons un scénario catastrophe dans lequel la NSA a imposé une backdoor dans rdrand, et que cette backdoor soit découverte par des personnes mal intentionnées, les dégâts seraient immenses. Edit Juin 2017 : j’ai rédigé ce scénario catastrophe en Mars 2017 et le mois qui a suivi, il s’est réalisé avec WannaCry, une faille découverte par la NSA et qui a été volée.
Pour plus d’information sur Rdrand, voir l’article de Ars Technica, la discussion sur Stack Exchange et les commentaires de Ycombinator.
Les assistances logicielles
haveged
Le paquet le plus connu pour alimenter le noyau en entropie et lui permettre de générer de l’aléatoire, c’est haveged. Son fonctionnement consiste à lire des états fugaces du processeur, qui devraient normalement être imprévisibles. Personne n’est en mesure de dire aujourd’hui si l’utilisation de haveged est sécurisée. La question fait débat mais le principe de précaution nous pousse à dire « non, pas trop ».
Ce qui est certain, c’est qu’il permet de générer des certificats SSL et GPG plus rapidement (exemple avec ce tutoriel).
Le principal risque lié à l’utilisation de haveged sur des machines virtuelles, c’est que les extensions du processeur sur lesquelles s’appuie haveged ne soient pas disponibles, ce qui pourrait conduire à générer une suite de zéro ou de un en lieu et place de données aléatoires. Ce serait la pire chose à faire pour la sécurité.
jitterentropy_rng
Depuis la version 4.2 du noyau Linux, un module est disponible : jitterentropy_rng. Il s’appuie sur la présence du timer haute résolution des processeurs modernes pour proposer une source aléatoire. Étant donné qu’il fait partie intégrante du noyau et que le développement de haveged semble en pause, c’est je pense une meilleure option que haveged. Voir plus d’information sur pthree.org.
Il semblerait néanmoins que le rythme de regénération de l’entropie soit inférieur avec jitterentropy_rng plutôt que haveged.
rng-tools
Le paquet rng-tools fournit le daemon rngd qui permet d’utiliser un périphérique matériel comme /dev/hwrng afin d’alimenter le noyau et /dev/random. Sur une machine physique, /dev/hwrng fait référence à un dispositif matériel comme ceux qui sont cités plus haut. Sur un hyperviseur comme KVM ou Xen, on peut utiliser virtio-rng qui permet à l’hyperviseur de donner accès à sa propre source d’aléatoire (matérielle ou logicielle).
On peut utiliser rngd pour injecter n’importe quel device ou FIFO dans /dev/random. Certains tutoriels conseillent d’utiliser /dev/urandom (exemple rngd -r /dev/urandom). Cela consiste à transformer urandom en random : à proscrire absolument car cela va à l’encontre de ce pourquoi ces devices ont été créés. Cela affaiblit énormément la qualité des nombres aléatoires produits, et fragilise les algorithmes cryptographiques qui reposent dessus.
De mon coté je l’utilise pour injecter le périphérique /dev/hwrng fourni à mes machines virtuelles KVM par le device virtio-rng dans /dev/random sur les noyaux les plus anciens (plus besoin avec Linux 4.2 et supérieurs).
Ecrire dans /dev/random
Cela n’a pas toujours été vrai dans les anciennes versions du noyau, mais on peut maintenant écrire dans /dev/random et le noyau utilisera les données envoyées pour alimenter son générateur de nombres aléatoires. Il vaut mieux savoir ce qu’on fait avant d’envoyer n’importe quoi.
random.org
Random-as-a-Service, c’est un peu la proposition de random.org. On interroge une API qui nous retourne des octets aléatoires grâce à un équipement matériel élaboré, un peu comme un serveur de temps basé sur une horloge atomique. Apparemment cet équipement est basé sur le bruit électromagnétique atmosphérique, c’est exactement ce que chacun peut faire chez soi avec rtl-sdr.
Pour tout ce qui a trait aux échanges chiffrés et la sécurité, je pense que c’est un non-sens d’utiliser random.org. Le risque d’interception des données est trop grand. C’est le générateur aléatoire local qui doit permettre de sécuriser des échanges, et non pas des échanges qui doivent sécuriser d’autres échanges voire un noyau complet.
Pour toutes les application non sécuritaires, pourquoi pas.
/dev/urandom ou /dev/random ?
La question se pose souvent dans la communauté, et pourtant la réponse est souvent la même : utilisez toujours /dev/urandom, même pour les applications de sécurité. D’un point de vue crypto, le niveau de qualité des deux périphériques est très proche, si bien qu’un n’existe aucune bonne raison d’utiliser /dev/random. Les développeurs de GPG et d’OpenSSL ont peut-être leurs raisons pour le faire, mais pas l’administrateur système lambda.
La différence entre ces deux périphériques, c’est que /dev/random est bloquant, c’est à dire qu’il va s’arrêter de délivrer des données si jamais le noyau vient à manquer d’entropie. A l’inverse, /dev/urandom est non-bloquant et le noyau fera ce qu’il faut à l’aide de fonctions de hachage pour continuer à débiter des octets.
Il existe un risque important à utiliser /dev/random, c’est de rendre l’application voire le serveur entier instable à cause d’un blocage de génération de données aléatoires. Une faille de sécurité béante qui pourrait être utilisée à mauvais escient. J’ai l’impression que lorsque /dev/random est utilisé, c’est pour des opérations rares, hors-ligne, et qui ont tout leur temps, comme la génération de certificats.
Regardez donc le fichier de configuration par défaut de mod_ssl, il n’est pas avare en explications.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<IfModule mod_ssl.c> # Pseudo Random Number Generator (PRNG): # Configure one or more sources to seed the PRNG of the SSL library. # The seed data should be of good random quality. # WARNING! On some platforms /dev/random blocks if not enough entropy # is available. This means you then cannot use the /dev/random device # because it would lead to very long connection times (as long as # it requires to make more entropy available). But usually those # platforms additionally provide a /dev/urandom device which doesn't # block. So, if available, use this one instead. Read the mod_ssl User # Manual for more details. # SSLRandomSeed startup builtin SSLRandomSeed startup file:/dev/urandom 512 SSLRandomSeed connect builtin SSLRandomSeed connect file:/dev/urandom 512 [...] |
Pour une discussion très détaillée sur ces deux périphériques, regardez la page « Myths about /dev/urandom« .
Conclusion
Connaître le fonctionnement du générateur de nombres pseudo-aléatoires est très intéressant, cela alimente la réflexion globale sur la sécurité du noyau et des échanges réseau.
Néanmoins, c’est à vouloir trop en faire à la va-vite qu’on risque d’altérer le comportement naturel du noyau et de commettre des bêtises. Pour un administrateur qui souhaite accélérer la génération des certificats, le réflexe c’est d’utiliser rngd à tort (en injectant urandom dans random) ou d’installer haveged à toutes les sauces. Il ne faut pas confondre le besoin pragmatique avec la théorie sous-jacente et les implications sécuritaires. Ce n’est pas parce que le chiffre d’entropie a miraculeusement augmenté que tous les moyens sont bons.
Il existe des suites logicielles supposées tester la qualité des nombres aléatoires comme rngtest et dieharder. Malheureusement, un test réussi ne signifie pas forcément que le système aléatoire est véritablement adapté à un usage sécuritaire. A vrai dire j’ai même pu lire que le nombre Pi pourrait bien passer certains tests.
Vous vous interrogez sur la meilleure source possible d’entropie pour votre usage ? C’est précisment le sujet de mon article Quel générateur RNG, et pour quel usage ?.
Merci pour ce papier vraiment clair et instructif. J’utilise haveged, qui est simple et pratique; mais je vais chercher mieux.
Bonjour Paul,
merci pour ce post qui se lit à merveille sur un sujet somme toute compliqué !
Comment connaitre exactement quelles sources d’entropie sont utilisées pour feed /dev/random ? Entre rdrand, les RNG matériels et les événements physiques clavier/souris, y a t il un moyen de le déterminer ?
Au cours de mes recherches de la soirée, je partage deux trouvailles intéressantes :
Entropy-as-a-Service avec Entropy Broker : https://www.vanheusden.com/entropybroker/
Pour compléter la partie Xen, il existe xentropyd pour envoyer l’entropie de dom0 aux DomU :
https://github.com/mirage/xentropyd
En tout cas j’ajoute ce blog à ma liste de lecture, votre style est très agréable à lire 🙂
Merci pour ce commentaire positif !
Dans les commentaires de random.c on trouve l’information suivante :
A cela s’ajoutent les fonctions au nom explicite : add_timer_randomness, add_hwgenerator_randomness.
L’instruction Intel rdrand ne sera jamais utilisée seule pour alimenter le pool d’entropie, c’est pour cela que Linus Torvalds juge qu’elle ne présente pas un risque pour le noyau. On peut lire dans random.c :
Il reste apparemment quelques fonctionnalités du noyau qui reposent sur elle (source).
Les RNG matériels accessibles par /dev/hwrng seront utilisés d’office par les noyaux récents. Mais rng-tools reste nécessaire pour les noyaux plus anciens.
Entropybrocker me fait penser à random.org. L’idée est séduisante mais il me semble paradoxal d’utiliser une connexion réseau pour alimenter un pool local d’entropie… qui servira en retour à sécuriser les connexions réseau SSL.
Enfin, pour aller plus loin, vous pouvez lire mon second article qui traite de générateurs RNG pour utilisation crypto.
Bonjour,
Article vraiment très intéressant 😉
Mais j’ai une question… A combien s’élève la quantité maximale d’entropie de Linux ? Et est ce que le système arrète d’en générer au bout d’un moment ? Car sur ma machine, l’entropie stagne vers les 3000 – 4000 (cat /proc/sys/kernel/random/entropy_avail) en temps normal…
Bonjour, et merci pour votre commentaire.
En effet, /proc/sys/kernel/random/entropy_avail ne dépassera jamais /proc/sys/kernel/random/poolsize.
Ce dernier a une valeur de 4096 bits qui est hardcodée dans random.c et qui est liée à la taille des (huge)pages.
Pour quelle raison voudriez-vous augmenter le poolsize ? J’ai l’intuition que la meilleure garantie d’imprévisibilité du PRNG est de fonctionner en « juste à temps ». De plus le débit autorisé par le périphérique urandom est considérable.
root@ordinateur:~# dd if=/dev/urandom of=/dev/null status=progress iflag=fullblock
2131219968 bytes (2,1 GB, 2,0 GiB) copied, 8 s, 266 MB/s
^C
Je ne voulais pas augmenter cette valeur. Je me demandais juste pourquoi elle ne depassait jamais les 4000 😉 Donc merci pour cette réponse 🙂
C’est avec plaisir, et ce fut l’occasion de me plonger dans random.c, ce que je n’avais jamais fait jusqu’à présent !