getrandom(2) system call
Linux 3.17から追加された,安全に random/urandom sourceからbyte列を読み出すためのsystem call. 基本的な用法に限定されるのであれば,自分で独自にreadするcodeを書くのではなく,こちらのsystem callを利用したほうが良い.
read from random source
3rd argに GRND_RANDOM というflagを渡すと,random source(Linuxが使用する乱数生成器及びそのdevice stream)を使用する.これはhardwareなどの状態やnoiseをもとにentropy poolを構成して,それをもとに乱数を生成するため,読み出すtimingによっては乱数を生成するのに十分なentropyの増大を待たなければならなくなる. getrandom(2) では ssize_t nread を返すため,十分なentropy poolが構成されていない場合は 2nd argに渡した buflen より少ないbyte列を読んで返す,みたいなこともある.
もしいかなるrandom byteも読み出せない場合, GRND_NONBLOCK flagが渡されているかによって挙動が異なる.flagが渡されていない場合はblockingが発生する.渡されていると即座に return -1され, errno に EAGAIN が設定される.
read from urandom source
特に指定しないと,urandom source(Linuxが提供する擬似乱数生成器及びそのdevice stream)を使用する.urandom sourceが初期化されていない状態でこのsystem callが呼び出されるとblockされる.3rd argに GRND_NONBLOCK というflagを渡したとき,先述したようにentropy poolの初期化がされていないためにbyte streamを読み出すことができず,即座に return -1され, errno に EAGAIN が設定される.
sample code
code:c
int main(int argc, char **argv)
{
if (argc != 2)
{
fprintf(stderr, "usage: ./getrandom_block <string>\n");
return EXIT_FAILURE;
}
size_t str_length = strlen(argv1); ssize_t nread;
char *random_buf;
if ((random_buf = malloc(str_length)) == NULL)
{
fprintf(stderr, "failed to alloc buffer\n");
return EXIT_FAILURE;
}
if ((nread = getrandom((void *)random_buf, str_length, 0)) != str_length)
{
fprintf(stderr, "failed to get random from random source\n");
return EXIT_FAILURE;
}
for (size_t i = 0; i < str_length; i++)
printf("xor-once%zu = '%c'\n", i, argv1i ^ random_bufi); for (size_t i = 0; i < str_length; i++)
printf("xor-twice%zu = '%c'\n", i, argv1i ^ random_bufi ^ random_bufi); free(random_buf);
return EXIT_SUCCESS;
}
Links