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 uu_sysrand_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             (void)n;
44             (void)fd;
45             (void)lose_counter;
46              
47             #ifdef HAVE_ARC4RANDOM
48 215           arc4random_buf(buf, nbytes);
49 215           return;
50             #endif
51             #ifdef HAVE_BCRYPTGENRANDOM
52             if (BCryptGenRandom(NULL, buf, nbytes, BCRYPT_USE_SYSTEM_PREFERRED_RNG) == 0)
53             return;
54             #endif
55             #ifdef HAVE_CRYPTGENRANDOM
56             {
57             int ok = 0;
58             HCRYPTPROV hCryptProv;
59             if (CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0)) {
60             ok = CryptGenRandom(hCryptProv, nbytes, buf);
61             CryptReleaseContext(hCryptProv, 0);
62             if (ok) return;
63             }
64             }
65             #endif
66             #ifdef HAVE_GETENTROPY
67             if (getentropy(buf, nbytes) == 0)
68             return;
69             #endif
70             #ifdef HAVE_GETRANDOM
71             if (getrandom(buf, nbytes, 0) == nbytes)
72             return;
73             #endif
74              
75             #ifndef WIN32
76             #ifndef USE_WIN32_NATIVE
77             fd = get_random_fd();
78             if (fd >= 0) {
79             while (n > 0) {
80             i = read(fd, cp, n);
81             if (i <= 0) {
82             if (lose_counter++ > 16)
83             break;
84             continue;
85             }
86             n -= i;
87             cp += i;
88             lose_counter = 0;
89             }
90             }
91             #endif
92             #endif
93              
94             /*
95             * We do this anyway, but this is the only source of
96             * randomness if /dev/random/urandom is out to lunch.
97             */
98             for (cp = buf, i = 0; i < nbytes; i++)
99             *cp++ ^= (rand() >> 7) & 0xFF;
100              
101             return;
102             }
103              
104             /* ex:set ts=2 sw=2 itab=spaces: */