File Coverage

ulib/sysrand.c
Criterion Covered Total %
statement 6 17 35.2
branch 0 8 0.0
condition n/a
subroutine n/a
pod n/a
total 6 25 24.0


line stmt bran cond sub pod time code
1             #ifdef __cplusplus
2             extern "C" {
3             #endif
4              
5             #include "ulib/sysrand.h"
6              
7             #ifdef __cplusplus
8             }
9             #endif
10              
11              
12             #ifndef WIN32
13             #ifndef USE_WIN32_NATIVE
14 0           static int get_random_fd(void)
15             {
16 0           int i, fd = -2;
17              
18 0 0         if (fd == -2) {
19 0           fd = open("/dev/urandom", O_RDONLY);
20 0 0         if (fd == -1)
21 0           fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
22 0 0         if (fd >= 0) {
23 0           i = fcntl(fd, F_GETFD);
24 0 0         if (i >= 0)
25 0           fcntl(fd, F_SETFD, i | FD_CLOEXEC);
26             }
27             }
28 0           return fd;
29             }
30             #endif
31             #endif
32              
33              
34             /*
35             * Generate a series of random bytes. Use /dev/urandom if possible,
36             * and if not, use srandom/random.
37             */
38 215           void sr_rand_bytes(void *buf, int nbytes)
39             {
40 215           int i, n = nbytes, fd;
41 215           int lose_counter = 0;
42 215           unsigned char *cp = buf;
43              
44             #ifdef HAVE_ARC4RANDOM
45 215           arc4random_buf(buf, nbytes);
46 215           return;
47             #endif
48             #ifdef HAVE_BCRYPTGENRANDOM
49             if (BCryptGenRandom(NULL, buf, nbytes, BCRYPT_USE_SYSTEM_PREFERRED_RNG) == 0)
50             return;
51             #endif
52             #ifdef HAVE_CRYPTGENRANDOM
53             {
54             int ok = 0;
55             HCRYPTPROV hCryptProv;
56             if (CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0)) {
57             ok = CryptGenRandom(hCryptProv, nbytes, buf);
58             CryptReleaseContext(hCryptProv, 0);
59             if (ok) return;
60             }
61             }
62             #endif
63             #ifdef HAVE_GETENTROPY
64             if (getentropy(buf, nbytes) == 0)
65             return;
66             #endif
67             #ifdef HAVE_GETRANDOM
68             if (getrandom(buf, nbytes, 0) == nbytes)
69             return;
70             #endif
71              
72             #ifndef WIN32
73             #ifndef USE_WIN32_NATIVE
74             fd = get_random_fd();
75             if (fd >= 0) {
76             while (n > 0) {
77             i = read(fd, cp, n);
78             if (i <= 0) {
79             if (lose_counter++ > 16)
80             break;
81             continue;
82             }
83             n -= i;
84             cp += i;
85             lose_counter = 0;
86             }
87             }
88             #endif
89             #endif
90              
91             /*
92             * We do this anyway, but this is the only source of
93             * randomness if /dev/random/urandom is out to lunch.
94             */
95             for (cp = buf, i = 0; i < nbytes; i++)
96             *cp++ ^= (rand() >> 7) & 0xFF;
97              
98             return;
99             }
100              
101             /* ex:set ts=2 sw=2 itab=spaces: */