VirtualBox

source: kBuild/trunk/src/sed/lib/getrandom.c@ 3613

Last change on this file since 3613 was 3613, checked in by bird, 7 months ago

src/sed: Merged in changes between 4.1.5 and 4.9 from the vendor branch. (svn merge /vendor/sed/4.1.5 /vendor/sed/current .)

File size: 5.6 KB
Line 
1/* Obtain a series of random bytes.
2
3 Copyright 2020-2022 Free Software Foundation, Inc.
4
5 This file is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as
7 published by the Free Software Foundation; either version 2.1 of the
8 License, or (at your option) any later version.
9
10 This file is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17
18/* Written by Paul Eggert. */
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
35typedef void * BCRYPT_ALG_HANDLE;
36# define BCRYPT_USE_SYSTEM_PREFERRED_RNG 0x00000002
37# if HAVE_LIB_BCRYPT
38extern 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/* Don't assume that UNICODE is not defined. */
54# undef LoadLibrary
55# define LoadLibrary LoadLibraryA
56# undef CryptAcquireContext
57# define CryptAcquireContext CryptAcquireContextA
58
59# if !HAVE_LIB_BCRYPT
60
61/* Avoid warnings from gcc -Wcast-function-type. */
62# define GetProcAddress \
63 (void *) GetProcAddress
64
65/* BCryptGenRandom with the BCRYPT_USE_SYSTEM_PREFERRED_RNG flag works only
66 starting with Windows 7. */
67typedef NTSTATUS (WINAPI * BCryptGenRandomFuncType) (BCRYPT_ALG_HANDLE, UCHAR *, ULONG, ULONG);
68static BCryptGenRandomFuncType BCryptGenRandomFunc = NULL;
69static BOOL initialized = FALSE;
70
71static void
72initialize (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/* These devices exist on all platforms except native Windows. */
91
92/* Name of a device through which the kernel returns high quality random
93 numbers, from an entropy pool. When the pool is empty, the call blocks
94 until entropy sources have added enough bits of entropy. */
95# ifndef NAME_OF_RANDOM_DEVICE
96# define NAME_OF_RANDOM_DEVICE "/dev/random"
97# endif
98
99/* Name of a device through which the kernel returns random or pseudo-random
100 numbers. It uses an entropy pool, but, in order to avoid blocking, adds
101 bits generated by a pseudo-random number generator, as needed. */
102# ifndef NAME_OF_NONCE_DEVICE
103# define NAME_OF_NONCE_DEVICE "/dev/urandom"
104# endif
105
106#endif
107
108/* Set BUFFER (of size LENGTH) to random bytes under the control of FLAGS.
109 Return the number of bytes written (> 0).
110 Upon error, return -1 and set errno. */
111ssize_t
112getrandom (void *buffer, size_t length, unsigned int flags)
113#undef getrandom
114{
115#if defined _WIN32 && ! defined __CYGWIN__
116 /* BCryptGenRandom, defined in <bcrypt.h>
117 <https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom>
118 with the BCRYPT_USE_SYSTEM_PREFERRED_RNG flag
119 works in Windows 7 and newer. */
120 static int bcrypt_not_working /* = 0 */;
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 /*STATUS_SUCCESS*/)
131 return length;
132 bcrypt_not_working = 1;
133 }
134# if !HAVE_LIB_BCRYPT
135 /* CryptGenRandom, defined in <wincrypt.h>
136 <https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptgenrandom>
137 works in older releases as well, but is now deprecated.
138 CryptAcquireContext, defined in <wincrypt.h>
139 <https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptacquirecontexta> */
140 {
141 static int crypt_initialized /* = 0 */;
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}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette