10#include <sys/random.h>
17 fprintf(stderr, "RNG FAIL line %d errno %d\n", __LINE__, errno); \
22static int test_device_writes(
void) {
23 const char*
paths[] = {
"/dev/random",
"/dev/urandom"};
24 unsigned char payload[513];
25 memset(payload, 0xa5,
sizeof(payload));
26 for (
size_t i = 0; i <
sizeof(
paths) /
sizeof(
paths[0]); ++i) {
27 int fd = open(
paths[i], O_WRONLY);
29 CHECK(write(fd, payload, 0) == 0);
30 CHECK(write(fd, payload,
sizeof(payload)) ==
sizeof(payload));
31 struct iovec vectors[] = {{payload, 7}, {payload, 0}, {payload + 7,
sizeof(payload) - 7}};
32 CHECK(writev(fd, vectors, 3) ==
sizeof(payload));
35 FILE* stream = fdopen(fd,
"w");
36 CHECK(stream != NULL);
37 CHECK(fwrite(payload, 1,
sizeof(payload), stream) ==
sizeof(payload));
38 CHECK(fflush(stream) == 0);
39 CHECK(fclose(stream) == 0);
41 puts(
"RNG-WRITE-PASS");
45int main(
int argc,
char** argv) {
46 unsigned char first[513], second[513];
47#if defined(__x86_64__)
48 unsigned a = 1, b, c, d;
49 __asm__
volatile(
"cpuid" :
"+a"(a),
"=b"(b),
"=c"(c),
"=d"(d));
50 unsigned rdrand = (c >> 30) & 1;
53 __asm__
volatile(
"cpuid" :
"+a"(a),
"=b"(b),
"+c"(c),
"=d"(d));
54 printf(
"RNG-CPU rdrand=%u rdseed=%u\n", rdrand, (b >> 18) & 1);
56 if (argc == 2 && !strcmp(argv[1],
"--unseeded")) {
58 CHECK(getrandom(first,
sizeof(first), GRND_NONBLOCK) == -1 && errno == EAGAIN);
59 CHECK(test_device_writes() == 0);
61 CHECK(getrandom(first,
sizeof(first), GRND_NONBLOCK) == -1 && errno == EAGAIN);
62 puts(
"RNG-UNSEEDED-PASS");
65 CHECK(test_device_writes() == 0);
66 CHECK(getauxval(AT_RANDOM) != 0);
67 CHECK(getrandom(first, 0, 0) == 0);
68 CHECK(getrandom(first, 256, 0) == 256);
69 CHECK(getrandom(second, 256, GRND_NONBLOCK) == 256);
70 CHECK(memcmp(first, second, 256) != 0);
72 CHECK(getrandom(first, 32, 0x40000000) == -1 && errno == EINVAL);
73 int random = open(
"/dev/urandom", O_RDONLY);
75 CHECK(read(random, first,
sizeof(first)) ==
sizeof(first));
76 CHECK(read(random, second,
sizeof(second)) ==
sizeof(second));
77 CHECK(memcmp(first, second,
sizeof(first)) != 0);
82 unsigned char seed[32];
83 } request = {256, 31, {0}};
85 CHECK(ioctl(random, 0x40085203UL, &request) == -1 && errno == EINVAL);
87 CHECK(ioctl(random, 0x40085203UL, (
void*)1) == -1 && errno == EFAULT);
91 CHECK(setuid(65534) == 0);
94 CHECK(ioctl(random, 0x40085203UL, &request) == -1 && (errno == EPERM || errno == EACCES));
98 CHECK(waitpid(child, &status, 0) == child && WIFEXITED(status) && !WEXITSTATUS(status));
103 for (
int i = 0; i < 4; ++i) {
105 CHECK(pipe(stream) == 0);
106 children[i] = fork();
107 CHECK(children[i] >= 0);
110 unsigned char sample[64];
111 CHECK(getrandom(sample,
sizeof(sample), 0) ==
sizeof(sample));
112 CHECK(write(stream[1], sample,
sizeof(sample)) ==
sizeof(sample));
116 readers[i] = stream[0];
118 unsigned char samples[4][64];
119 for (
int i = 0; i < 4; ++i) {
120 CHECK(read(readers[i], samples[i],
sizeof(samples[i])) ==
sizeof(samples[i]));
122 CHECK(waitpid(children[i], &status, 0) == children[i] && WIFEXITED(status) &&
123 !WEXITSTATUS(status));
124 for (
int j = 0; j < i; ++j)
125 CHECK(memcmp(samples[i], samples[j],
sizeof(samples[i])) != 0);
127 puts(
"RNG-SEEDED-PASS");