]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: Support getentropy and arc4random in std::random_device
authorJonathan Wakely <jwakely@redhat.com>
Thu, 4 Nov 2021 15:51:37 +0000 (15:51 +0000)
committerJonathan Wakely <jwakely@redhat.com>
Tue, 9 Nov 2021 14:40:33 +0000 (14:40 +0000)
This adds additional "getentropy" and "arc4random" tokens to
std::random_device. The former is supported on Glibc and OpenBSD (and
apparently wasm), and the latter is supported on various BSDs.

libstdc++-v3/ChangeLog:

* acinclude.m4 (GLIBCXX_CHECK_GETENTROPY, GLIBCXX_CHECK_ARC4RANDOM):
Define.
* configure.ac (GLIBCXX_CHECK_GETENTROPY, GLIBCXX_CHECK_ARC4RANDOM):
Use them.
* config.h.in: Regenerate.
* configure: Regenerate.
* src/c++11/random.cc (random_device): Add getentropy and
arc4random as sources.
* testsuite/26_numerics/random/random_device/cons/token.cc:
Check new tokens.
* testsuite/26_numerics/random/random_device/entropy.cc:
Likewise.

libstdc++-v3/acinclude.m4
libstdc++-v3/config.h.in
libstdc++-v3/configure
libstdc++-v3/configure.ac
libstdc++-v3/src/c++11/random.cc
libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc
libstdc++-v3/testsuite/26_numerics/random/random_device/entropy.cc

index 90ecc4a87a2531cf8cb6c96afd34cac1251d4155..497af5723e158abdadf8fdd7932d9f5e45cfd1f5 100644 (file)
@@ -4830,6 +4830,52 @@ AC_DEFUN([GLIBCXX_CHECK_EXCEPTION_PTR_SYMVER], [
   fi
 ])
 
+dnl
+dnl Check whether getentropy is present in <unistd.h>.
+dnl
+AC_DEFUN([GLIBCXX_CHECK_GETENTROPY], [
+
+  AC_LANG_SAVE
+  AC_LANG_CPLUSPLUS
+  AC_MSG_CHECKING([for getentropy])
+  AC_CACHE_VAL(glibcxx_cv_getentropy, [
+      AC_TRY_COMPILE(
+       [#include <unistd.h>],
+       [unsigned i;
+        ::getentropy(&i, sizeof(i));],
+       [glibcxx_cv_getentropy=yes], [glibcxx_cv_getentropy=no])
+    ])
+
+  if test $glibcxx_cv_getentropy = yes; then
+    AC_DEFINE(HAVE_GETENTROPY, 1, [Define if getentropy is available in <unistd.h>.])
+  fi
+  AC_MSG_RESULT($glibcxx_cv_getentropy)
+  AC_LANG_RESTORE
+])
+
+dnl
+dnl Check whether arc4random is present in <stdlib.h>.
+dnl
+AC_DEFUN([GLIBCXX_CHECK_ARC4RANDOM], [
+
+  AC_LANG_SAVE
+  AC_LANG_CPLUSPLUS
+  AC_MSG_CHECKING([for arc4random])
+  AC_CACHE_VAL(glibcxx_cv_arc4random, [
+      AC_TRY_COMPILE(
+       [#include <stdlib.h>],
+       [unsigned i = ::arc4random();],
+       [glibcxx_cv_arc4random=yes], [glibcxx_cv_arc4random=no])
+    ])
+
+  if test $glibcxx_cv_arc4random = yes; then
+    AC_DEFINE(HAVE_ARC4RANDOM, 1, [Define if arc4random is available in <stdlib.h>.])
+  fi
+  AC_MSG_RESULT($glibcxx_cv_arc4random)
+  AC_LANG_RESTORE
+])
+
+
 # Macros from the top-level gcc directory.
 m4_include([../config/gc++filt.m4])
 m4_include([../config/tls.m4])
index 228a758325ef7ad8b0b37b1b797a069307f2945d..420021fcb1af54c4d6de6794852f3eb90481b681 100644 (file)
@@ -9,6 +9,9 @@
 /* Define to 1 if you have the `aligned_alloc' function. */
 #undef HAVE_ALIGNED_ALLOC
 
+/* Define if arc4random is available in <stdlib.h>. */
+#undef HAVE_ARC4RANDOM
+
 /* Define to 1 if you have the <arpa/inet.h> header file. */
 #undef HAVE_ARPA_INET_H
 
 /* Define to 1 if you have the `frexpl' function. */
 #undef HAVE_FREXPL
 
+/* Define if getentropy is available in <unistd.h>. */
+#undef HAVE_GETENTROPY
+
 /* Define if _Unwind_GetIPInfo is available. */
 #undef HAVE_GETIPINFO
 
index c1aea82707011f52937a63685d6642633b81e405..21371031b66174a301fa00145815d282ccf0ef6c 100755 (executable)
@@ -75429,6 +75429,109 @@ $as_echo "#define _GLIBCXX_X86_RDSEED 1" >>confdefs.h
 $as_echo "$ac_cv_x86_rdseed" >&6; }
 
 
+# Check for other random number APIs
+
+
+
+  ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getentropy" >&5
+$as_echo_n "checking for getentropy... " >&6; }
+  if ${glibcxx_cv_getentropy+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <unistd.h>
+int
+main ()
+{
+unsigned i;
+        ::getentropy(&i, sizeof(i));
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  glibcxx_cv_getentropy=yes
+else
+  glibcxx_cv_getentropy=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+
+
+  if test $glibcxx_cv_getentropy = yes; then
+
+$as_echo "#define HAVE_GETENTROPY 1" >>confdefs.h
+
+  fi
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_getentropy" >&5
+$as_echo "$glibcxx_cv_getentropy" >&6; }
+  ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+  ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for arc4random" >&5
+$as_echo_n "checking for arc4random... " >&6; }
+  if ${glibcxx_cv_arc4random+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+int
+main ()
+{
+unsigned i = ::arc4random();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  glibcxx_cv_arc4random=yes
+else
+  glibcxx_cv_arc4random=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+
+
+  if test $glibcxx_cv_arc4random = yes; then
+
+$as_echo "#define HAVE_ARC4RANDOM 1" >>confdefs.h
+
+  fi
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_arc4random" >&5
+$as_echo "$glibcxx_cv_arc4random" >&6; }
+  ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
 # This depends on GLIBCXX_ENABLE_SYMVERS and GLIBCXX_IS_NATIVE.
 
   # Do checks for resource limit functions.
index 2d68b3672b9631a8bbf20b409724574e64c68fda..5b3c92f4bd7a7a994992f71178fbde4cce1cc881 100644 (file)
@@ -468,6 +468,10 @@ GLIBCXX_CHECK_X86_RDRAND
 # Check if assembler supports rdseed opcode.
 GLIBCXX_CHECK_X86_RDSEED
 
+# Check for other random number APIs
+GLIBCXX_CHECK_GETENTROPY
+GLIBCXX_CHECK_ARC4RANDOM
+
 # This depends on GLIBCXX_ENABLE_SYMVERS and GLIBCXX_IS_NATIVE.
 GLIBCXX_CONFIGURE_TESTSUITE
 
index 4b88818646f14fef3996ddd7521166b3501963a0..4a553e0d84fd6c435ffe1b17907e7b9f993817ef 100644 (file)
 # include <stdlib.h>
 #endif
 
-#if defined _GLIBCXX_USE_CRT_RAND_S || defined _GLIBCXX_USE_DEV_RANDOM
+#ifdef _GLIBCXX_HAVE_GETENTROPY
+# include <unistd.h>
+#endif
+
+#if defined _GLIBCXX_USE_CRT_RAND_S || defined _GLIBCXX_USE_DEV_RANDOM \
+  || _GLIBCXX_HAVE_GETENTROPY
 // The OS provides a source of randomness we can use.
 # pragma GCC poison _M_mt
 #elif defined USE_RDRAND || defined USE_RDSEED || defined USE_DARN
@@ -166,6 +171,25 @@ namespace std _GLIBCXX_VISIBILITY(default)
     }
 #endif
 
+#ifdef _GLIBCXX_HAVE_GETENTROPY
+    unsigned int
+    __libc_getentropy(void*)
+    {
+      unsigned int val;
+      if (::getentropy(&val, sizeof(val)) != 0)
+       std::__throw_runtime_error(__N("random_device: getentropy failed"));
+      return val;
+    }
+#endif
+
+#ifdef _GLIBCXX_HAVE_ARC4RANDOM
+    unsigned int
+    __libc_arc4random(void*)
+    {
+      return ::arc4random();
+    }
+#endif
+
 #ifdef USE_LCG
     // TODO: use this to seed std::mt19937 engine too.
     unsigned
@@ -214,7 +238,7 @@ namespace std _GLIBCXX_VISIBILITY(default)
 #endif
 
     enum Which : unsigned {
-      device_file = 1, prng = 2, rand_s = 4,
+      device_file = 1, prng = 2, rand_s = 4, getentropy = 8, arc4random = 16,
       rdseed = 64, rdrand = 128, darn = 256,
       any = 0xffff
     };
@@ -256,6 +280,16 @@ namespace std _GLIBCXX_VISIBILITY(default)
        return device_file;
 #endif
 
+#ifdef _GLIBCXX_HAVE_ARC4RANDOM
+      if (func == __libc_arc4random)
+       return arc4random;
+#endif
+
+#ifdef _GLIBCXX_HAVE_GETENTROPY
+      if (func == __libc_getentropy)
+       return getentropy;
+#endif
+
 #ifdef USE_LCG
       if (func == &__lcg)
        return prng;
@@ -311,6 +345,14 @@ namespace std _GLIBCXX_VISIBILITY(default)
     else if (token == "rand_s")
       which = rand_s;
 #endif // _GLIBCXX_USE_CRT_RAND_S
+#ifdef _GLIBCXX_HAVE_GETENTROPY
+    else if (token == "getentropy")
+      which = getentropy;
+#endif // _GLIBCXX_HAVE_GETENTROPY
+#ifdef _GLIBCXX_HAVE_ARC4RANDOM
+    else if (token == "arc4random")
+      which = arc4random;
+#endif // _GLIBCXX_HAVE_ARC4RANDOM
 #ifdef _GLIBCXX_USE_DEV_RANDOM
     else if (token == "/dev/urandom" || token == "/dev/random")
       {
@@ -395,6 +437,26 @@ namespace std _GLIBCXX_VISIBILITY(default)
       }
 #endif // USE_DARN
 
+#ifdef _GLIBCXX_HAVE_ARC4RANDOM
+    if (which & arc4random)
+      {
+       _M_func = &__libc_arc4random;
+       return;
+      }
+#endif // _GLIBCXX_HAVE_ARC4RANDOM
+
+#ifdef _GLIBCXX_HAVE_GETENTROPY
+    if (which & getentropy)
+      {
+       unsigned int i;
+       if (::getentropy(&i, sizeof(i)) == 0) // On linux the syscall can fail.
+         {
+           _M_func = &__libc_getentropy;
+           return;
+         }
+      }
+#endif // _GLIBCXX_HAVE_GETENTROPY
+
 #ifdef _GLIBCXX_USE_DEV_RANDOM
     if (which & device_file)
     {
@@ -548,6 +610,9 @@ namespace std _GLIBCXX_VISIBILITY(default)
     case rdseed:
     case darn:
       return (double) max;
+    case arc4random:
+    case getentropy:
+      return (double) max;
     case rand_s:
     case prng:
       return 0.0;
index 07713e5c67fa0e74a845621e73199d37e3ad436c..e56afbc9c975c9dcbc1c297d9e326fd2a9da22f6 100644 (file)
@@ -53,6 +53,7 @@ test03()
   const std::string tokens[] = {
     "rdseed", "rdrand", "darn",
     "rand_s", "/dev/urandom", "/dev/random",
+    "getentropy", "arc4random",
     "mt19937", "prng"
   };
   int count = 0;
index 6f3ebb1b38e3b49a29fd6be70406eaea8d4e6326..63b7043bf9b77230072f7c1377951fa453351135 100644 (file)
@@ -28,6 +28,13 @@ test01()
       const double entropy = std::random_device(token).entropy();
       VERIFY( entropy == max );
     }
+
+    for (auto token : { "getentropy", "arc4random" })
+    if (__gnu_test::random_device_available(token))
+    {
+      const double entropy = std::random_device(token).entropy();
+      VERIFY( entropy == max );
+    }
 }
 
 int