mirror of
https://git.savannah.gnu.org/git/gnulib.git
synced 2025-08-10 04:43:00 +03:00
Prefer the C23 style to the C99 style, since the stdbool module now supports C23. * lib/acl-internal.h, lib/acl.h, lib/argmatch.c, lib/argmatch.h: * lib/argp-help.c, lib/argv-iter.h, lib/asyncsafe-spin.c: * lib/backup-internal.h, lib/backupfile.c, lib/base32.h: * lib/base64.h, lib/basename-lgpl.c, lib/bitset/base.h: * lib/c-ctype.h, lib/c-strcasestr.c, lib/canonicalize-lgpl.c: * lib/canonicalize.c, lib/chdir-long.c, lib/chown.c: * lib/classpath.h, lib/clean-temp-private.h: * lib/clean-temp-simple.c, lib/clean-temp-simple.h: * lib/clean-temp.c, lib/clean-temp.h, lib/cloexec.h: * lib/close-stream.c, lib/closein.c, lib/closeout.c, lib/closeout.h: * lib/csharpcomp.h, lib/csharpexec.h, lib/cycle-check.c: * lib/cycle-check.h, lib/des.h, lib/dfa.h, lib/diffseq.h: * lib/dirname.h, lib/exclude.c, lib/exclude.h, lib/execute.c: * lib/execute.h, lib/execvpe.c, lib/fatal-signal.c, lib/fchdir.c: * lib/file-set.h, lib/filevercmp.c, lib/findprog-in.c: * lib/findprog.c, lib/findprog.h, lib/fma.c, lib/fnmatch.c: * lib/fopen.c, lib/freadable.h, lib/freading.h, lib/freopen-safer.c: * lib/fstrcmp.c, lib/fsusage.h, lib/fts.c, lib/fwritable.h: * lib/fwriteerror.c, lib/fwriting.h, lib/gen-uni-tables.c: * lib/getaddrinfo.c, lib/getcwd.c, lib/getloadavg.c: * lib/getndelim2.c, lib/getpass.c, lib/getrandom.c: * lib/git-merge-changelog.c, lib/gl_list.h, lib/gl_map.h: * lib/gl_omap.h, lib/gl_oset.h, lib/gl_set.h, lib/glob.c: * lib/glthread/cond.h, lib/hamt.h, lib/hard-locale.h: * lib/hash-triple.h, lib/hash.h, lib/human.h, lib/i-ring.h: * lib/isapipe.c, lib/javacomp.h, lib/javaexec.h, lib/javaversion.c: * lib/lchown.c, lib/localeinfo.h, lib/localename.c: * lib/long-options.h, lib/malloc/dynarray.h, lib/mbchar.h: * lib/mbfile.h, lib/mbiter.h, lib/mbmemcasecoll.h, lib/mbscasestr.c: * lib/mbsstr.c, lib/mbuiter.h, lib/mkdir-p.h, lib/modechange.h: * lib/mountlist.h, lib/nanosleep.c, lib/nonblocking.h: * lib/nstrftime.c, lib/openat.c, lib/openat.h, lib/os2-spawn.c: * lib/parse-datetime.h, lib/pipe-filter-aux.c, lib/pipe-filter-gi.c: * lib/pipe-filter-ii.c, lib/pipe-filter.h, lib/posixtm.h: * lib/priv-set.c, lib/progreloc.c, lib/propername.c: * lib/pthread-spin.c, lib/quotearg.c, lib/readtokens.c: * lib/readtokens0.h, lib/readutmp.c, lib/regex-quote.h: * lib/regex_internal.h, lib/relocwrapper.c, lib/rename.c: * lib/renameatu.c, lib/rpmatch.c, lib/same.c, lib/same.h: * lib/save-cwd.c, lib/savewd.c, lib/savewd.h, lib/spawn-pipe.h: * lib/spawni.c, lib/stack.h, lib/stat.c, lib/stdckdint.in.h: * lib/strcasestr.c, lib/strfmon_l.c, lib/striconveh.c: * lib/striconveha.h, lib/string-buffer.h, lib/strptime.c: * lib/strstr.c, lib/strtod.c, lib/supersede.h, lib/system-quote.c: * lib/tempname.c, lib/term-style-control.c: * lib/term-style-control.h, lib/textstyle.in.h, lib/time_rz.c: * lib/tmpdir.c, lib/tmpdir.h, lib/tmpfile.c, lib/unicase.in.h: * lib/unicase/caseprop.h, lib/unicase/invariant.h: * lib/unicase/u16-casemap.c, lib/unicase/u16-ct-totitle.c: * lib/unicase/u16-is-invariant.c, lib/unicase/u32-casemap.c: * lib/unicase/u32-ct-totitle.c, lib/unicase/u32-is-invariant.c: * lib/unicase/u8-casemap.c, lib/unicase/u8-ct-totitle.c: * lib/unicase/u8-is-invariant.c, lib/unictype.in.h: * lib/unigbrk.in.h, lib/unigbrk/u16-grapheme-breaks.c: * lib/unigbrk/u32-grapheme-breaks.c: * lib/unigbrk/u8-grapheme-breaks.c: * lib/unigbrk/uc-grapheme-breaks.c, lib/uniname/uniname.c: * lib/unistr.in.h, lib/unlinkdir.h, lib/userspec.h, lib/utime.c: * lib/utimecmp.c, lib/utimens.c, lib/wait-process.h: * lib/windows-cond.c, lib/windows-spawn.c, lib/windows-spawn.h: * lib/windows-timedrwlock.c, lib/write-any-file.h, lib/xbinary-io.c: * lib/xstrtod.h, lib/yesno.h: * tests/nap.h, tests/qemu.h, tests/test-areadlink-with-size.c: * tests/test-areadlink.c, tests/test-areadlinkat-with-size.c: * tests/test-areadlinkat.c, tests/test-base32.c: * tests/test-base64.c, tests/test-ceil2.c, tests/test-ceilf2.c: * tests/test-chown.c, tests/test-dirname.c, tests/test-dup-safer.c: * tests/test-dup3.c, tests/test-exclude.c: * tests/test-execute-child.c, tests/test-execute-main.c: * tests/test-execute-script.c, tests/test-explicit_bzero.c: * tests/test-fchownat.c, tests/test-fcntl-safer.c: * tests/test-fcntl.c, tests/test-fdutimensat.c: * tests/test-filenamecat.c, tests/test-floor2.c: * tests/test-floorf2.c, tests/test-fstatat.c, tests/test-fstrcmp.c: * tests/test-futimens.c, tests/test-getlogin.h, tests/test-getopt.h: * tests/test-hard-locale.c, tests/test-hash.c: * tests/test-idpriv-drop.c, tests/test-idpriv-droptemp.c: * tests/test-immutable.c, tests/test-intprops.c: * tests/test-lchown.c, tests/test-link.c, tests/test-linkat.c: * tests/test-lstat.c, tests/test-mbmemcasecmp.c: * tests/test-mbmemcasecoll.c, tests/test-mkdir.c: * tests/test-mkdirat.c, tests/test-mkfifo.c, tests/test-mkfifoat.c: * tests/test-mknod.c, tests/test-nonblocking-pipe-child.c: * tests/test-nonblocking-pipe-main.c: * tests/test-nonblocking-socket-child.c: * tests/test-nonblocking-socket-main.c, tests/test-open.c: * tests/test-openat.c, tests/test-pipe.c, tests/test-pipe2.c: * tests/test-poll.c, tests/test-posix_spawn-chdir.c: * tests/test-posix_spawn-dup2-stdin.c: * tests/test-posix_spawn-dup2-stdout.c: * tests/test-posix_spawn-fchdir.c, tests/test-posix_spawn-open1.c: * tests/test-posix_spawn-open2.c, tests/test-quotearg-simple.c: * tests/test-quotearg.c, tests/test-readlink.c: * tests/test-readlinkat.c, tests/test-readtokens.c: * tests/test-rename.c, tests/test-renameat.c: * tests/test-renameatu.c, tests/test-rmdir.c, tests/test-round2.c: * tests/test-select.h, tests/test-spawn-pipe-child.c: * tests/test-spawn-pipe-main.c, tests/test-spawn-pipe-script.c: * tests/test-stack.c, tests/test-stat.c, tests/test-supersede.c: * tests/test-symlink.c, tests/test-symlinkat.c: * tests/test-system-quote-main.c: * tests/test-term-style-control-hello.c: * tests/test-term-style-control-yes.c, tests/test-timespec.c: * tests/test-trunc2.c, tests/test-truncf2.c, tests/test-unlink.c: * tests/test-unlinkat.c, tests/test-userspec.c, tests/test-utime.c: * tests/test-utimens.c, tests/test-utimensat.c: * tests/unictype/test-categ_byname.c: * tests/unigbrk/test-uc-is-grapheme-break.c: Don’t include stdbool.h. * modules/acl, modules/xgetcwd: Don’t depend on stdbool, as these modules don’t use bool. * modules/argp, modules/bitset, modules/diffseq, modules/file-has-acl: * modules/gen-uni-tables, modules/getrandom: * modules/hash-triple-simple, modules/posix_spawn-internal: * modules/strcasestr, modules/supersede, modules/system-quote: * modules/uniconv/base, modules/uniname/uniname, modules/utime: * modules/windows-timedrwlock: Depend on stdbool, as these modules use bool.
191 lines
5.6 KiB
C
191 lines
5.6 KiB
C
/* Obtain a series of random bytes.
|
|
|
|
Copyright 2020-2022 Free Software Foundation, Inc.
|
|
|
|
This file is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU Lesser General Public License as
|
|
published by the Free Software Foundation; either version 2.1 of the
|
|
License, or (at your option) any later version.
|
|
|
|
This file is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public License
|
|
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
|
|
|
/* Written by Paul Eggert. */
|
|
|
|
#include <config.h>
|
|
|
|
#include <sys/random.h>
|
|
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
|
|
#if defined _WIN32 && ! defined __CYGWIN__
|
|
# define WIN32_LEAN_AND_MEAN
|
|
# include <windows.h>
|
|
# if HAVE_BCRYPT_H
|
|
# include <bcrypt.h>
|
|
# else
|
|
# define NTSTATUS LONG
|
|
typedef void * BCRYPT_ALG_HANDLE;
|
|
# define BCRYPT_USE_SYSTEM_PREFERRED_RNG 0x00000002
|
|
# if HAVE_LIB_BCRYPT
|
|
extern NTSTATUS WINAPI BCryptGenRandom (BCRYPT_ALG_HANDLE, UCHAR *, ULONG, ULONG);
|
|
# endif
|
|
# endif
|
|
# if !HAVE_LIB_BCRYPT
|
|
# include <wincrypt.h>
|
|
# ifndef CRYPT_VERIFY_CONTEXT
|
|
# define CRYPT_VERIFY_CONTEXT 0xF0000000
|
|
# endif
|
|
# endif
|
|
#endif
|
|
|
|
#include "minmax.h"
|
|
|
|
#if defined _WIN32 && ! defined __CYGWIN__
|
|
|
|
/* Don't assume that UNICODE is not defined. */
|
|
# undef LoadLibrary
|
|
# define LoadLibrary LoadLibraryA
|
|
# undef CryptAcquireContext
|
|
# define CryptAcquireContext CryptAcquireContextA
|
|
|
|
# if !HAVE_LIB_BCRYPT
|
|
|
|
/* Avoid warnings from gcc -Wcast-function-type. */
|
|
# define GetProcAddress \
|
|
(void *) GetProcAddress
|
|
|
|
/* BCryptGenRandom with the BCRYPT_USE_SYSTEM_PREFERRED_RNG flag works only
|
|
starting with Windows 7. */
|
|
typedef NTSTATUS (WINAPI * BCryptGenRandomFuncType) (BCRYPT_ALG_HANDLE, UCHAR *, ULONG, ULONG);
|
|
static BCryptGenRandomFuncType BCryptGenRandomFunc = NULL;
|
|
static BOOL initialized = FALSE;
|
|
|
|
static void
|
|
initialize (void)
|
|
{
|
|
HMODULE bcrypt = LoadLibrary ("bcrypt.dll");
|
|
if (bcrypt != NULL)
|
|
{
|
|
BCryptGenRandomFunc =
|
|
(BCryptGenRandomFuncType) GetProcAddress (bcrypt, "BCryptGenRandom");
|
|
}
|
|
initialized = TRUE;
|
|
}
|
|
|
|
# else
|
|
|
|
# define BCryptGenRandomFunc BCryptGenRandom
|
|
|
|
# endif
|
|
|
|
#else
|
|
/* These devices exist on all platforms except native Windows. */
|
|
|
|
/* Name of a device through which the kernel returns high quality random
|
|
numbers, from an entropy pool. When the pool is empty, the call blocks
|
|
until entropy sources have added enough bits of entropy. */
|
|
# ifndef NAME_OF_RANDOM_DEVICE
|
|
# define NAME_OF_RANDOM_DEVICE "/dev/random"
|
|
# endif
|
|
|
|
/* Name of a device through which the kernel returns random or pseudo-random
|
|
numbers. It uses an entropy pool, but, in order to avoid blocking, adds
|
|
bits generated by a pseudo-random number generator, as needed. */
|
|
# ifndef NAME_OF_NONCE_DEVICE
|
|
# define NAME_OF_NONCE_DEVICE "/dev/urandom"
|
|
# endif
|
|
|
|
#endif
|
|
|
|
/* Set BUFFER (of size LENGTH) to random bytes under the control of FLAGS.
|
|
Return the number of bytes written (> 0).
|
|
Upon error, return -1 and set errno. */
|
|
ssize_t
|
|
getrandom (void *buffer, size_t length, unsigned int flags)
|
|
#undef getrandom
|
|
{
|
|
#if defined _WIN32 && ! defined __CYGWIN__
|
|
/* BCryptGenRandom, defined in <bcrypt.h>
|
|
<https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom>
|
|
with the BCRYPT_USE_SYSTEM_PREFERRED_RNG flag
|
|
works in Windows 7 and newer. */
|
|
static int bcrypt_not_working /* = 0 */;
|
|
if (!bcrypt_not_working)
|
|
{
|
|
# if !HAVE_LIB_BCRYPT
|
|
if (!initialized)
|
|
initialize ();
|
|
# endif
|
|
if (BCryptGenRandomFunc != NULL
|
|
&& BCryptGenRandomFunc (NULL, buffer, length,
|
|
BCRYPT_USE_SYSTEM_PREFERRED_RNG)
|
|
== 0 /*STATUS_SUCCESS*/)
|
|
return length;
|
|
bcrypt_not_working = 1;
|
|
}
|
|
# if !HAVE_LIB_BCRYPT
|
|
/* CryptGenRandom, defined in <wincrypt.h>
|
|
<https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptgenrandom>
|
|
works in older releases as well, but is now deprecated.
|
|
CryptAcquireContext, defined in <wincrypt.h>
|
|
<https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptacquirecontexta> */
|
|
{
|
|
static int crypt_initialized /* = 0 */;
|
|
static HCRYPTPROV provider;
|
|
if (!crypt_initialized)
|
|
{
|
|
if (CryptAcquireContext (&provider, NULL, NULL, PROV_RSA_FULL,
|
|
CRYPT_VERIFY_CONTEXT))
|
|
crypt_initialized = 1;
|
|
else
|
|
crypt_initialized = -1;
|
|
}
|
|
if (crypt_initialized >= 0)
|
|
{
|
|
if (!CryptGenRandom (provider, length, buffer))
|
|
{
|
|
errno = EIO;
|
|
return -1;
|
|
}
|
|
return length;
|
|
}
|
|
}
|
|
# endif
|
|
errno = ENOSYS;
|
|
return -1;
|
|
#elif HAVE_GETRANDOM
|
|
return getrandom (buffer, length, flags);
|
|
#else
|
|
static int randfd[2] = { -1, -1 };
|
|
bool devrandom = (flags & GRND_RANDOM) != 0;
|
|
int fd = randfd[devrandom];
|
|
|
|
if (fd < 0)
|
|
{
|
|
static char const randdevice[][MAX (sizeof NAME_OF_NONCE_DEVICE,
|
|
sizeof NAME_OF_RANDOM_DEVICE)]
|
|
= { NAME_OF_NONCE_DEVICE, NAME_OF_RANDOM_DEVICE };
|
|
int oflags = (O_RDONLY + O_CLOEXEC
|
|
+ (flags & GRND_NONBLOCK ? O_NONBLOCK : 0));
|
|
fd = open (randdevice[devrandom], oflags);
|
|
if (fd < 0)
|
|
{
|
|
if (errno == ENOENT || errno == ENOTDIR)
|
|
errno = ENOSYS;
|
|
return -1;
|
|
}
|
|
randfd[devrandom] = fd;
|
|
}
|
|
|
|
return read (fd, buffer, length);
|
|
#endif
|
|
}
|