File Coverage

entropy.c
Criterion Covered Total %
statement 10 28 35.7
branch 4 16 25.0
condition n/a
subroutine n/a
pod n/a
total 14 44 31.8


line stmt bran cond sub pod time code
1             #include
2             #include "entropy.h"
3              
4             /* A fallback timer entropy method that will probably never be used. */
5             #if defined(_WIN32_WCE)
6             static UV timer_entropy(UV bytes, unsigned char* buf) { return 0; }
7             #else
8             #include
9 0           static uint32_t mix32(uint32_t r0) { /* Similar to PCG 32 */
10 0           uint32_t word = ((r0 >> ((r0 >> 28u) + 4u)) ^ r0) * 277803737u;
11 0           return (word >> 22u) ^ word;
12             }
13 0           static uint32_t timer_mix8(uint32_t acc) {
14             clock_t t1;
15             uint32_t bit, a;
16 0 0         for (bit = a = 0; bit < 8; bit++) {
17 0 0         t1 = clock(); while (t1 == clock()) a ^= 1;
18 0           acc = (acc << 1) | a;
19             }
20 0           return mix32(acc);
21             }
22 0           static UV timer_entropy(UV bytes, unsigned char* buf) {
23             UV byte;
24 0           uint32_t acc = 0;
25              
26 0 0         for (byte = 0; byte < 4; byte++)
27 0           acc = timer_mix8(acc);
28 0 0         for (byte = 0; byte < bytes; byte++) {
29 0           acc = timer_mix8( timer_mix8( acc ) );
30 0           buf[byte] = (acc >> 24) & 0xFF;
31             }
32 0           return bytes;
33             }
34             #endif
35              
36 72           UV get_entropy_bytes(UV bytes, unsigned char* buf)
37             {
38 72           UV len = 0;
39              
40             #if defined(_WIN32) || defined(_WIN32_WCE)
41             #ifndef _WIN32_WINNT
42             #define _WIN32_WINNT 0x0400
43             #endif
44             #ifdef _WIN32_WCE
45             #define UNDER_CE
46             #define ARM
47             #endif
48              
49             #define WIN32_LEAN_AND_MEAN
50             #include
51             #include
52              
53             /* TODO: Calling RtlGenRandom is faster */
54              
55             HCRYPTPROV hProv = 0;
56             if (!CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL,
57             CRYPT_SILENT | CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET) &&
58             !CryptAcquireContext (&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL,
59             CRYPT_SILENT | CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET))
60             return 0;
61              
62             if (CryptGenRandom(hProv, bytes, buf) == TRUE)
63             len = bytes;
64             CryptReleaseContext(hProv, 0);
65              
66             #else /* ^^^^^^ Windows ^^^^^^ vvvvvv /dev/urandom vvvvvvv */
67              
68 72           FILE *f = fopen("/dev/urandom", "rb");
69              
70 72 50         if (f == NULL)
71 0           f = fopen("/dev/random", "rb");
72              
73 72 50         if (f != NULL) {
74 72 50         if (setvbuf(f, NULL, _IONBF, 0) == 0) { /* disable buffering */
75 72           len = (UV)fread(buf, 1, (size_t)bytes, f);
76             }
77 72           fclose(f);
78             }
79              
80             #endif
81              
82             /* Do a fallback method if something didn't work right. */
83 72 50         if (len != bytes)
84 0           len = timer_entropy(bytes, buf);
85              
86 72           return len;
87             }