RANDOM(4)

NAZWA
random, urandom - urządzenia źródłowe liczb losowych jądra

SKŁADNIA
#include <linux/random.h>

int ioctl(fd, RNDżądanie, parametr);

OPIS
Specjalne urządzenia znakowe /dev/random i /dev/urandom (obecne w Linuksie od wersji 1.3.30) stanowią interfejs do wbudowanego w jądro generatora liczb losowych. Plik /dev/random ma numer główny urządzenia 1 i numer poboczny 8. Plik /dev/urandom ma numer główny urządzenia 1 i numer poboczny 9.

Generator liczb losowych zbiera szum środowiskowy ze sterowników urządzeń i innych źródeł do puli losowej (puli entropii). Generator przechowuje również szacunkową liczbę bitów szumu w puli losowej. Z puli tej tworzone są liczby losowe.

Linux 3.17 i późniejsze zapewnia prostszy i bezpieczniejszy interfejs getrandom(2), który nie wymaga plików specjalnych; więcej informacji w podręczniku getrandom(2).

Przy odczycie, urzadzenie /dev/urandom zwraca losowe bajty, wygenerowane za pomocą pseudolosowego generatora liczb, który pozyskuje ziarno z puli entropii. Odczyt z tego urządzenia nie blokuje się (nie dochodzi do zjawiska CPU yield), ale przy pozyskiwaniu znaczących ilości danych może wystąpić znaczące opóźnienie.

Podczas odczytu we wczesnej fazie rozruchu, /dev/urandom może zwrócić dane jeszcze przed zainicjowaniem puli losowej. Zastosowanie getrandom(2) lub /dev/random nie będzie podatne na to niekorzystne zjawisko.

Urządzenie /dev/random jest przestarzałym interfejsem, pochodzącym jeszcze z czasów, gdy implementacja kryptograficznych funkcji pierwotnych (ang. cryptographic primitives) użyta w implementacji /dev/urandom nie była uważana za zaufaną. Zwraca losowe bajty w miarę napływu świeżego szumu do puli losowej i blokuje się, gdy jest to konieczne. Urządzenie /dev/random jest odpowiednie do aplikacji wymagających losowości wysokiej jakości, które mogą sobie pozwolić na opóźnienia o nieznanej długości.

Jeśli pula losowa jest pusta, odczyt z /dev/random będzie wstrzymany do czasu zebrania dodatkowego szumu środowiskowego. Jeśli open(2) jest wywołane do /dev/random z flagą O_NONBLOCK, kolejne read(2) nie będzie blokowane, jeśli żądana liczba bajtów nie jest dostępna. W zamian zwracane są dostępne bajty. Jeśli nie ma dostępnych bajtów, read(2) zwróci -1, a errno ustawi się na EAGAIN.

Flaga O_NONBLOCK nie ma znaczenia przy otwieraniu /dev/urandom. Podczas wywołania read(2) do urządzenia /dev/urandom, odczyt do 256 bajtów zwróci żądaną wielkość bajtów; nie można ich przerwać sygnałem. Odczyt przy użyciu bufora ponad ten limit może zwrócić mniejszą liczbę bajtów niż żądana lub nie powieść się z błędem EINTR, jeśli nastąpi przerwanie sygnałem.

Od Linuksa 3.16, read(2) z /dev/urandom zwróci co najwyżej 32 MB. read(2) z /dev/random zwróci nie więcej niż 512 bajtów (przed jądrami Linux w wersji 2.6.12 - 340 bajtów).

Pisanie do /dev/random lub /dev/urandom zaktualizuje pulę entropii za pomocą pisanych danych, lecz nie zwiększy poziomu entropii. Oznacza to, że będzie to miało wpływ na odczyt z obu plików, lecz nie uczyni odczytu z /dev/random szybszym.

  Użycie
Urządzenie /dev/random jest uważane za przestarzały interfejs, a /dev/urandom jest preferowany i wystarczający we wszystkich przypadkach, z wyjątkiem aplikacji wymagających losowości we wczesnej fazie rozruchu, które muszą korzystać z getrandom(2), blokującego się do czasu zainicjowania puli losowej.

Jeśli plik puli losowej jest przechowywany pomiędzy ponownymi uruchomieniami, zgodnie z poniższymi zaleceniami, wyjście jest kryptograficznie bezpieczne w stosunku do atakujących bez dostępu do lokalnego roota, zaraz po przeładowaniu go w sekwencji rozruchowej i odnosi się w całości do sieciowych kluczy szyfrujących sesji (wszystkie główne dystrybucje Linuksa zachowują plik puli losowej pomiędzy rozruchami od co najmniej 2000 roku). Ponieważ odczyt z /dev/random może nie być płynny, użytkownicy będą go z reguły chcieli otworzyć w trybie nieblokującym (lub przeprowadzać odczyt z czasem oczekiwania) i udostępniać jakiś typ powiadomienia dla użytkownika, jeśli oczekiwana losowość nie jest od razu dostępna.

  Konfiguracja
Jeśli w systemie nie ma plików /dev/random i /dev/urandom, można je utworzyć przy użyciu następujących poleceń:

    mknod -m 666 /dev/random c 1 8
    mknod -m 666 /dev/urandom c 1 9
    chown root:root /dev/random /dev/urandom

Gdy Linux uruchamiany jest przy niewielkim udziale operatora, pula losowa może być w dość przewidywalnym stanie. Faktyczna ilość szumu w puli losowej jest wówczas poniżej ilości szacowanej. Aby przeciwdziałać temu efektowi, pomocne jest zapamiętywanie informacji o puli losowej pomiędzy kolejnymi uruchomieniami systemu. Aby działo się to automatycznie, należy dodać wiersze do stosownych skryptów startowych Linuksa:

    echo "Inicjowanie generatora liczb losowych..."
    random_seed=/var/run/random-seed
    # Przechowanie wartości losowej od jednego startu systemu
    # do kolejnego startu. Ładowanie oraz późniejsze zachowywanie
    # całej puli losowej.
    if [ -f $random_seed ]; then
        cat $random_seed >/dev/urandom
    else
        touch $random_seed
    fi
    chmod 600 $random_seed
    poolfile=/proc/sys/kernel/random/poolsize
    [ -r $poolfile ] && bits=$(cat $poolfile) || bits=4096
    bytes=$(expr $bits / 8)
    dd if=/dev/urandom of=$random_seed count=1 bs=$bytes

Trzeba również dodać następujące wiersze do stosownego skryptu uruchamianego podczas zamykania systemu Linuksa:

    # Przechowanie losowych danych pomiędzy wyłączeniem a włączeniem
    # komputera. Zachowywanie puli losowej generatora.
    echo "Zachowywanie puli losowej..."
    random_seed=/var/run/random-seed
    touch $random_seed
    chmod 600 $random_seed
    poolfile=/proc/sys/kernel/random/poolsize
    [ -r $poolfile ] && bits=$(cat $poolfile) || bits=4096
    bytes=$(expr $bits / 8)
    dd if=/dev/urandom of=$random_seed count=1 bs=$bytes

W powyższych przykładach zakładamy, że Linux jest w wersji 2.6.0 lub nowszej, gdzie /proc/sys/kernel/random/poolsize zwraca rozmiar puli entropii w bitach (zob. niżej).

  Interfejsy /proc
Pliki w katalogu /proc/sys/kernel/random (obecnym od wersji 2.3.16) udostępniają dodatkowe informacje o urządzeniu /dev/random:

entropy_avail
    Plik z prawami tylko do odczytu, dostarcza dostępną entropię, w bitach. Będzie to wielkość w zakresie od 0 do 4096.

poolsize
    Plik zawiera rozmiar puli losowej. Format tego pliku zależy od wersji jądra:

    Linux 2.4:
        Plik podaje rozmiar puli losowej w bajtach. Zazwyczaj - 512 (bajtów). Plik jest zapisywalny i może być zmieniony na dowolną wartość, dla której dostępny jest algorytm. Obecnie możliwe wartości to: 32, 64, 128, 256, 512, 1024 lub 2048.

    Linux 2.6 i późniejsze:
        Plik jest dostępny tylko do odczytu i podaje rozmiar puli losowej w bitach. Zawiera wartość 4096.

read_wakeup_threshold
    Plik zawiera liczbę bitów entropii wymaganej do obudzenia procesu, który zasnął w oczekiwaniu na entropię z urządzenia /dev/random. Domyślna wartość do 64.

write_wakeup_threshold
    Plik zawiera liczbę bitów entropii poniżej której zostanie uśpiony proces, który wykona select(2) lub poll(2), aby otworzyć do zapisu urządzenie /dev/random. Wartości te mogą być zmienione przez zapis do tych plików.

uuid i boot_id
    Pliki te zawierają losowe łańcuchy znaków, takie jak 6fd5a44b-35f4-4ad4-a9b9-6b9be13e1fe9. Pierwszy z tych plików jest generowany na nowo przy każdym odczycie, a drugi jest generowany tylko raz.

  Interfejs ioctl(2)
Następujące żądania ioctl(2) są zdefiniowane na deskryptorach plików połączonych z /dev/random lub /dev/urandom. Wszystkie przeprowadzone żądania wpływają na wejściową pulę entropii zarówno /dev/random jak i /dev/urandom. Możliwość CAP_SYS_ADMIN jest wymagana przez wszystkie żądania za wyjątkiem RNDGETENTCNT.

RNDGETENTCNT
    Zbiera wartość entropii z puli wejściowej, zawartość będzie taka sama jak pliku entropy_avail w katalogu proc. Wyniki zostaną przechowane w liczbie całkowitej wskazanej przez argument.

RNDADDTOENTCNT
    Zwiększa lub zmniejsza wartość entropii z puli wejściowej o wartość wskazaną przez argument.

RNDGETPOOL
    Usunięte w Linuksie 2.6.9

RNDADDENTROPY
    Dodaje dodatkową entropię do puli wejściowej, zwiększając wartość entropii. Różni się to od zapisu do /dev/random lub /dev/urandom, które dodaje pewne dane, lecz nie zwiększa wartości entropii. Używana jest poniższa struktura:

        struct rand_pool_info {
            int    wartość_entropii;
            int    wiel_buf;
            __u32  buf[0];
        };

    Wartość_entropii to wartość dodawana (lub odejmowana) od wartości losowej, buf to bufor o wielkości wiel_buf dodawany do puli losowej.

RNDZAPENTCNT, RNDCLEARPOOL
    Zeruje wielkość entropii we wszystkich pulach i dodaje do nich pewne dane systemowe (np. rzeczywisty czas trwania - tzw. wall clock).

PLIKI
/dev/random
/dev/urandom

UWAGI
Przegląd i porównanie różnych interfejsów do pozyskiwania losowości znajduje się w podręczniku random(7).

BŁĘDY
Podczas wczesnej fazy rozruchu, /dev/urandom może zwrócić dane jeszcze przed zainicjowaniem puli losowej.

ZOBACZ TAKŻE
mknod(1), getrandom(2), random(7)

RFC 1750, "Randomness Recommendations for Security"

O STRONIE
Angielska wersja tej strony pochodzi z wydania 5.13 projektu Linux man-pages. Opis projektu, informacje dotyczące zgłaszania błędów oraz najnowszą wersję oryginału można znaleźć pod adresem https://www.kernel.org/doc/man-pages/.

TŁUMACZENIE
Autorami polskiego tłumaczenia niniejszej strony podręcznika są: Paweł Olszewski <alder@amg.net.pl>, Robert Luberda <robert@debian.org> i Michał Kułach <michal.kulach@gmail.com>

Niniejsze tłumaczenie jest wolną dokumentacją. Bliższe informacje o warunkach licencji można uzyskać zapoznając się z GNU General Public License w wersji 3 (https://www.gnu.org/licenses/gpl-3.0.html) lub nowszej. Nie przyjmuje się ŻADNEJ ODPOWIEDZIALNOŚCI.

Błędy w tłumaczeniu strony podręcznika prosimy zgłaszać na adres listy dyskusyjnej manpages-pl-list@lists.sourceforge.net.