This source file includes following definitions.
- initialize
- getrandom
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include <config.h>
21
22 #include <sys/random.h>
23
24 #include <errno.h>
25 #include <fcntl.h>
26 #include <stdbool.h>
27 #include <unistd.h>
28
29 #if defined _WIN32 && ! defined __CYGWIN__
30 # define WIN32_LEAN_AND_MEAN
31 # include <windows.h>
32 # if HAVE_BCRYPT_H
33 # include <bcrypt.h>
34 # else
35 # define NTSTATUS LONG
36 typedef void * BCRYPT_ALG_HANDLE;
37 # define BCRYPT_USE_SYSTEM_PREFERRED_RNG 0x00000002
38 # if HAVE_LIB_BCRYPT
39 extern NTSTATUS WINAPI BCryptGenRandom (BCRYPT_ALG_HANDLE, UCHAR *, ULONG, ULONG);
40 # endif
41 # endif
42 # if !HAVE_LIB_BCRYPT
43 # include <wincrypt.h>
44 # ifndef CRYPT_VERIFY_CONTEXT
45 # define CRYPT_VERIFY_CONTEXT 0xF0000000
46 # endif
47 # endif
48 #endif
49
50 #include "minmax.h"
51
52 #if defined _WIN32 && ! defined __CYGWIN__
53
54
55 # undef LoadLibrary
56 # define LoadLibrary LoadLibraryA
57 # undef CryptAcquireContext
58 # define CryptAcquireContext CryptAcquireContextA
59
60 # if !HAVE_LIB_BCRYPT
61
62
63 # define GetProcAddress \
64 (void *) GetProcAddress
65
66
67
68 typedef NTSTATUS (WINAPI * BCryptGenRandomFuncType) (BCRYPT_ALG_HANDLE, UCHAR *, ULONG, ULONG);
69 static BCryptGenRandomFuncType BCryptGenRandomFunc = NULL;
70 static BOOL initialized = FALSE;
71
72 static void
73 initialize (void)
74 {
75 HMODULE bcrypt = LoadLibrary ("bcrypt.dll");
76 if (bcrypt != NULL)
77 {
78 BCryptGenRandomFunc =
79 (BCryptGenRandomFuncType) GetProcAddress (bcrypt, "BCryptGenRandom");
80 }
81 initialized = TRUE;
82 }
83
84 # else
85
86 # define BCryptGenRandomFunc BCryptGenRandom
87
88 # endif
89
90 #else
91
92
93
94
95
96 # ifndef NAME_OF_RANDOM_DEVICE
97 # define NAME_OF_RANDOM_DEVICE "/dev/random"
98 # endif
99
100
101
102
103 # ifndef NAME_OF_NONCE_DEVICE
104 # define NAME_OF_NONCE_DEVICE "/dev/urandom"
105 # endif
106
107 #endif
108
109
110
111
112 ssize_t
113 getrandom (void *buffer, size_t length, unsigned int flags)
114 #undef getrandom
115 {
116 #if defined _WIN32 && ! defined __CYGWIN__
117
118
119
120
121 static int bcrypt_not_working ;
122 if (!bcrypt_not_working)
123 {
124 # if !HAVE_LIB_BCRYPT
125 if (!initialized)
126 initialize ();
127 # endif
128 if (BCryptGenRandomFunc != NULL
129 && BCryptGenRandomFunc (NULL, buffer, length,
130 BCRYPT_USE_SYSTEM_PREFERRED_RNG)
131 == 0 )
132 return length;
133 bcrypt_not_working = 1;
134 }
135 # if !HAVE_LIB_BCRYPT
136
137
138
139
140
141 {
142 static int crypt_initialized ;
143 static HCRYPTPROV provider;
144 if (!crypt_initialized)
145 {
146 if (CryptAcquireContext (&provider, NULL, NULL, PROV_RSA_FULL,
147 CRYPT_VERIFY_CONTEXT))
148 crypt_initialized = 1;
149 else
150 crypt_initialized = -1;
151 }
152 if (crypt_initialized >= 0)
153 {
154 if (!CryptGenRandom (provider, length, buffer))
155 {
156 errno = EIO;
157 return -1;
158 }
159 return length;
160 }
161 }
162 # endif
163 errno = ENOSYS;
164 return -1;
165 #elif HAVE_GETRANDOM
166 return getrandom (buffer, length, flags);
167 #else
168 static int randfd[2] = { -1, -1 };
169 bool devrandom = (flags & GRND_RANDOM) != 0;
170 int fd = randfd[devrandom];
171
172 if (fd < 0)
173 {
174 static char const randdevice[][MAX (sizeof NAME_OF_NONCE_DEVICE,
175 sizeof NAME_OF_RANDOM_DEVICE)]
176 = { NAME_OF_NONCE_DEVICE, NAME_OF_RANDOM_DEVICE };
177 int oflags = (O_RDONLY + O_CLOEXEC
178 + (flags & GRND_NONBLOCK ? O_NONBLOCK : 0));
179 fd = open (randdevice[devrandom], oflags);
180 if (fd < 0)
181 {
182 if (errno == ENOENT || errno == ENOTDIR)
183 errno = ENOSYS;
184 return -1;
185 }
186 randfd[devrandom] = fd;
187 }
188
189 return read (fd, buffer, length);
190 #endif
191 }