mirror of
https://https.git.savannah.gnu.org/git/gnulib.git
synced 2026-04-28 06:33:36 +00:00
getrandom: Add support for native Windows.
* lib/getrandom.c: Include <errno.h>, <windows.h>, <bcrypt.h>, <wincrypt.h>. (CRYPT_VERIFY_CONTEXT): New macro. (LoadLibrary, CryptAcquireContext): Redirect to the variant with suffix 'A'. (GetProcAddress): New macro. (BCryptGenRandomFuncType): New type. (BCryptGenRandomFunc, initialized): New variables. (initialize): New function. (getrandom): On native Windows, use <bcrypt.h> API when available, and <wincrypt.h> API as fallback. * m4/getrandom.m4 (gl_FUNC_GETRANDOM): Set LIB_GETRANDOM. * modules/getrandom (Link): New section. * modules/getentropy (Link): Likewise. * modules/getrandom-tests (Makefile.am): Link test-getrandom against $(LIB_GETRANDOM). * modules/getentropy-tests (Makefile.am): Link test-getentropy against $(LIB_GETRANDOM). * modules/sys_random-c++-tests (Makefile.am): Link test-sys_random-c++ against $(LIB_GETRANDOM). * doc/glibc-functions/getrandom.texi: Mention the native Windows support.
This commit is contained in:
26
ChangeLog
26
ChangeLog
@@ -1,3 +1,29 @@
|
||||
2020-05-31 Bruno Haible <bruno@clisp.org>
|
||||
|
||||
getrandom: Add support for native Windows.
|
||||
* lib/getrandom.c: Include <errno.h>, <windows.h>, <bcrypt.h>,
|
||||
<wincrypt.h>.
|
||||
(CRYPT_VERIFY_CONTEXT): New macro.
|
||||
(LoadLibrary, CryptAcquireContext): Redirect to the variant with suffix
|
||||
'A'.
|
||||
(GetProcAddress): New macro.
|
||||
(BCryptGenRandomFuncType): New type.
|
||||
(BCryptGenRandomFunc, initialized): New variables.
|
||||
(initialize): New function.
|
||||
(getrandom): On native Windows, use <bcrypt.h> API when available, and
|
||||
<wincrypt.h> API as fallback.
|
||||
* m4/getrandom.m4 (gl_FUNC_GETRANDOM): Set LIB_GETRANDOM.
|
||||
* modules/getrandom (Link): New section.
|
||||
* modules/getentropy (Link): Likewise.
|
||||
* modules/getrandom-tests (Makefile.am): Link test-getrandom against
|
||||
$(LIB_GETRANDOM).
|
||||
* modules/getentropy-tests (Makefile.am): Link test-getentropy against
|
||||
$(LIB_GETRANDOM).
|
||||
* modules/sys_random-c++-tests (Makefile.am): Link test-sys_random-c++
|
||||
against $(LIB_GETRANDOM).
|
||||
* doc/glibc-functions/getrandom.texi: Mention the native Windows
|
||||
support.
|
||||
|
||||
2020-05-31 Bruno Haible <bruno@clisp.org>
|
||||
|
||||
getrandom: Simplify the determination of the random number devices.
|
||||
|
||||
@@ -22,7 +22,7 @@ Portability problems fixed by Gnulib:
|
||||
@item
|
||||
This function is missing on some platforms:
|
||||
glibc 2.24, Mac OS X 10.5, FreeBSD 11.0, NetBSD 5.0, OpenBSD 3.8,
|
||||
Solaris 11.0, Android 9.0.
|
||||
Solaris 11.0, mingw, MSVC 14, Android 9.0.
|
||||
@item
|
||||
This function has a different return type on some platforms:
|
||||
Solaris 11.4.
|
||||
@@ -32,5 +32,5 @@ Portability problems not fixed by Gnulib:
|
||||
@itemize
|
||||
@item
|
||||
This function is missing on some platforms:
|
||||
Minix 3.1.8, IRIX 6.5, mingw, MSVC 14.
|
||||
Minix 3.1.8, IRIX 6.5.
|
||||
@end itemize
|
||||
|
||||
104
lib/getrandom.c
104
lib/getrandom.c
@@ -21,14 +21,65 @@
|
||||
|
||||
#include <sys/random.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if defined _WIN32 && ! defined __CYGWIN__
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <windows.h>
|
||||
# include <bcrypt.h>
|
||||
# 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. */
|
||||
#if !(defined _WIN32 && ! defined __CYGWIN__)
|
||||
|
||||
/* 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
|
||||
@@ -52,7 +103,56 @@ ssize_t
|
||||
getrandom (void *buffer, size_t length, unsigned int flags)
|
||||
#undef getrandom
|
||||
{
|
||||
#if HAVE_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 };
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# getrandom.m4 serial 4
|
||||
# getrandom.m4 serial 5
|
||||
dnl Copyright 2020 Free Software Foundation, Inc.
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
dnl gives unlimited permission to copy and/or distribute it,
|
||||
@@ -33,4 +33,32 @@ AC_DEFUN([gl_FUNC_GETRANDOM],
|
||||
REPLACE_GETRANDOM=1
|
||||
fi
|
||||
fi
|
||||
|
||||
case "$host_os" in
|
||||
mingw*)
|
||||
AC_CACHE_CHECK([whether the bcrypt library is guaranteed to be present],
|
||||
[gl_cv_lib_assume_bcrypt],
|
||||
[AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[#include <windows.h>]],
|
||||
[[#if !(_WIN32_WINNT >= _WIN32_WINNT_WIN7)
|
||||
cannot assume it
|
||||
#endif
|
||||
]])
|
||||
],
|
||||
[gl_cv_lib_assume_bcrypt=yes],
|
||||
[gl_cv_lib_assume_bcrypt=no])
|
||||
])
|
||||
if test $gl_cv_lib_assume_bcrypt = yes; then
|
||||
AC_DEFINE([HAVE_LIB_BCRYPT], [1],
|
||||
[Define to 1 if the bcrypt library is guaranteed to be present.])
|
||||
LIB_GETRANDOM='-lbcrypt'
|
||||
else
|
||||
LIB_GETRANDOM='-ladvapi32'
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
LIB_GETRANDOM= ;;
|
||||
esac
|
||||
AC_SUBST([LIB_GETRANDOM])
|
||||
])
|
||||
|
||||
@@ -22,6 +22,9 @@ Makefile.am:
|
||||
Include:
|
||||
<unistd.h>
|
||||
|
||||
Link:
|
||||
$(LIB_GETRANDOM)
|
||||
|
||||
License:
|
||||
LGPL
|
||||
|
||||
|
||||
@@ -10,3 +10,4 @@ configure.ac:
|
||||
Makefile.am:
|
||||
TESTS += test-getentropy
|
||||
check_PROGRAMS += test-getentropy
|
||||
test_getentropy_LDADD = $(LDADD) $(LIB_GETRANDOM)
|
||||
|
||||
@@ -23,6 +23,9 @@ Makefile.am:
|
||||
Include:
|
||||
<sys/random.h>
|
||||
|
||||
Link:
|
||||
$(LIB_GETRANDOM)
|
||||
|
||||
License:
|
||||
LGPL
|
||||
|
||||
|
||||
@@ -10,3 +10,4 @@ configure.ac:
|
||||
Makefile.am:
|
||||
TESTS += test-getrandom
|
||||
check_PROGRAMS += test-getrandom
|
||||
test_getrandom_LDADD = $(LDADD) @LIB_GETRANDOM@
|
||||
|
||||
@@ -15,4 +15,5 @@ if ANSICXX
|
||||
TESTS += test-sys_random-c++
|
||||
check_PROGRAMS += test-sys_random-c++
|
||||
test_sys_random_c___SOURCES = test-sys_random-c++.cc
|
||||
test_sys_random_c___LDADD = $(LDADD) $(LIB_GETRANDOM)
|
||||
endif
|
||||
|
||||
Reference in New Issue
Block a user