summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2022-04-09 15:48:16 +0900
committerTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2022-04-09 17:23:00 +0900
commitba3396f7bb210b53fb940f274a0622ad9799545c (patch)
treee186e0c5b27cc146810a0ddcba95866f6a67bce9
parent851a74f53e6128019dbfff7d410e91c9d4d03799 (diff)
Better entropy for getRandomBytes
-rw-r--r--configure.ac1
-rw-r--r--src/SimpleRandomizer.cc48
-rw-r--r--test/Makefile.am3
-rw-r--r--test/SimpleRandomizerTest.cc70
4 files changed, 111 insertions, 11 deletions
diff --git a/configure.ac b/configure.ac
index 56481fd2..10acaba0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -754,6 +754,7 @@ AC_CHECK_FUNCS([__argz_count \
atexit \
ftruncate \
getcwd \
+ getentropy \
gethostbyaddr \
gethostbyname \
getifaddrs \
diff --git a/src/SimpleRandomizer.cc b/src/SimpleRandomizer.cc
index 8a055d66..8dbef82f 100644
--- a/src/SimpleRandomizer.cc
+++ b/src/SimpleRandomizer.cc
@@ -39,6 +39,11 @@
#include <cstdlib>
#include <cassert>
#include <cstring>
+#include <iostream>
+
+#ifdef __APPLE__
+# include <Security/SecRandom.h>
+#endif // __APPLE__
#include "a2time.h"
#include "a2functional.h"
@@ -89,17 +94,40 @@ void SimpleRandomizer::getRandomBytes(unsigned char* buf, size_t len)
{
#ifdef __MINGW32__
BOOL r = CryptGenRandom(provider_, len, reinterpret_cast<BYTE*>(buf));
- assert(r);
-#else // ! __MINGW32__
- auto ubuf = reinterpret_cast<result_type*>(buf);
- size_t q = len / sizeof(result_type);
- auto dis = std::uniform_int_distribution<result_type>();
- for (; q > 0; --q, ++ubuf) {
- *ubuf = dis(gen_);
+ if (!r) {
+ assert(r);
+ abort();
+ }
+#elif defined(__APPLE__)
+ auto rv = SecRandomCopyBytes(kSecRandomDefault, len, buf);
+ assert(errSecSuccess == rv);
+#else // !__MINGW32__ && !__APPLE__
+ constexpr static size_t blocklen = 256;
+ auto iter = len / blocklen;
+ auto p = buf;
+
+ for (size_t i = 0; i < iter; ++i) {
+ auto rv = getentropy(p, blocklen);
+ if (rv != 0) {
+ std::cerr << "getentropy: " << strerror(errno) << std::endl;
+ assert(0);
+ abort();
+ }
+
+ p += blocklen;
+ }
+
+ auto rem = len - iter * blocklen;
+ if (rem == 0) {
+ return;
+ }
+
+ auto rv = getentropy(p, rem);
+ if (rv != 0) {
+ std::cerr << "getentropy: " << strerror(errno) << std::endl;
+ assert(0);
+ abort();
}
- const size_t r = len % sizeof(result_type);
- auto last = dis(gen_);
- memcpy(ubuf, &last, r);
#endif // ! __MINGW32__
}
diff --git a/test/Makefile.am b/test/Makefile.am
index c7114449..49c6211f 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -89,7 +89,8 @@ aria2c_SOURCES = AllTest.cc\
WrDiskCacheTest.cc\
WrDiskCacheEntryTest.cc\
GroupIdTest.cc\
- IndexedListTest.cc
+ IndexedListTest.cc \
+ SimpleRandomizerTest.cc
if ENABLE_XML_RPC
aria2c_SOURCES += XmlRpcRequestParserControllerTest.cc
diff --git a/test/SimpleRandomizerTest.cc b/test/SimpleRandomizerTest.cc
new file mode 100644
index 00000000..59e134aa
--- /dev/null
+++ b/test/SimpleRandomizerTest.cc
@@ -0,0 +1,70 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2022 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "SimpleRandomizer.h"
+
+#include <set>
+#include <array>
+
+#include <cppunit/extensions/HelperMacros.h>
+
+namespace aria2 {
+
+class SimpleRandomizerTest : public CppUnit::TestFixture {
+ CPPUNIT_TEST_SUITE(SimpleRandomizerTest);
+ CPPUNIT_TEST(testGetRandomBytes);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testGetRandomBytes();
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SimpleRandomizerTest);
+
+void SimpleRandomizerTest::testGetRandomBytes()
+{
+ std::set<std::string> set;
+
+ constexpr size_t n = 5000;
+
+ for (size_t i = 0; i < 5000; ++i) {
+ std::array<unsigned char, 257> buf;
+ SimpleRandomizer::getInstance()->getRandomBytes(buf.data(), buf.size());
+ set.emplace(std::begin(buf), std::end(buf));
+ }
+
+ CPPUNIT_ASSERT_EQUAL(n, set.size());
+}
+
+} // namespace aria2