1
0
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:
Bruno Haible
2020-05-31 18:23:04 +02:00
parent 053dd57da2
commit 8175e3ddda
9 changed files with 168 additions and 5 deletions

View File

@@ -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.

View File

@@ -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

View File

@@ -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 };

View File

@@ -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])
])

View File

@@ -22,6 +22,9 @@ Makefile.am:
Include:
<unistd.h>
Link:
$(LIB_GETRANDOM)
License:
LGPL

View File

@@ -10,3 +10,4 @@ configure.ac:
Makefile.am:
TESTS += test-getentropy
check_PROGRAMS += test-getentropy
test_getentropy_LDADD = $(LDADD) $(LIB_GETRANDOM)

View File

@@ -23,6 +23,9 @@ Makefile.am:
Include:
<sys/random.h>
Link:
$(LIB_GETRANDOM)
License:
LGPL

View File

@@ -10,3 +10,4 @@ configure.ac:
Makefile.am:
TESTS += test-getrandom
check_PROGRAMS += test-getrandom
test_getrandom_LDADD = $(LDADD) @LIB_GETRANDOM@

View File

@@ -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