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