1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
#include <time.h>
#include "grv.h"
#ifdef __unix__
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
static int xread(int fd, void *buf, size_t count)
{
char *b = (char *)buf;
int n = 0;
int rv;
while ( count ) {
rv = read(fd, b, count);
if ( rv == -1 ) {
if ( errno == EINTR || errno == EAGAIN )
continue;
else
return n ? n : -1;
} else if ( rv == 0 ) {
return n;
}
count -= rv;
n += rv;
b += rv;
}
return n;
}
static int randfd = -1;
int get_random_bytes(void *ptr, int len)
{
/* We might have /dev/urandom */
if (randfd < 0) {
randfd = open("/dev/urandom", O_RDONLY);
if (randfd < 0)
return -1;
/*
* File descriptors are closed automatically on process exit, so
* we don't bother setting up atexit() here.
*/
}
return xread(randfd, ptr, len) == len ? 0 : -1;
}
#elif defined(__WIN32__)
#include <windows.h>
#include <wincrypt.h>
static HCRYPTPROV hProv;
static int provider_open = 0;
static void close_provider(void)
{
CryptReleaseContext(hProv, 0);
provider_open = 0;
}
int get_random_bytes(void *ptr, int len)
{
BOOL ok;
static const DWORD providers[] = {
PROV_RNG, PROV_INTEL_SEC, PROV_RSA_SIG, PROV_RSA_FULL,
PROV_DSS, PROV_SSL, 0
};
if (!provider_open) {
const DWORD *pp = providers;
while (*pp) {
if (CryptAcquireContext(&hProv, NULL, NULL, *pp,
CRYPT_SILENT | CRYPT_VERIFYCONTEXT))
goto found;
pp++;
}
return -1; /* No provider available */
found:
provider_open = 1;
atexit(close_provider);
}
ok = CryptGenRandom(hProv, len, ptr);
return ok ? 0 : -1;
}
#else
/* Need system-specific code here */
int get_random_bytes(void *ptr, int len)
{
return -1;
}
#endif
void randomize(void)
{
unsigned long key_array[32/sizeof(unsigned long)];
key_array[0] = time(0); /* Better than nothing on failure*/
get_random_bytes(key_array, sizeof key_array);
init_by_array(key_array, sizeof key_array/(sizeof key_array[0]));
}
|