aboutsummaryrefslogtreecommitdiffstats
path: root/libqpdf/QUtil.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libqpdf/QUtil.cc')
-rw-r--r--libqpdf/QUtil.cc114
1 files changed, 35 insertions, 79 deletions
diff --git a/libqpdf/QUtil.cc b/libqpdf/QUtil.cc
index 01e0b6e7..c5fe535c 100644
--- a/libqpdf/QUtil.cc
+++ b/libqpdf/QUtil.cc
@@ -3,6 +3,10 @@
#include <qpdf/QUtil.hh>
#include <qpdf/PointerHolder.hh>
+#ifdef USE_INSECURE_RANDOM
+# include <qpdf/InsecureRandomDataProvider.hh>
+#endif
+#include <qpdf/SecureRandomDataProvider.hh>
#include <cmath>
#include <iomanip>
@@ -18,7 +22,6 @@
#include <Windows.h>
#include <direct.h>
#include <io.h>
-#include <Wincrypt.h>
#else
#include <unistd.h>
#endif
@@ -383,38 +386,7 @@ QUtil::toUTF8(unsigned long uval)
return result;
}
-#ifdef USE_INSECURE_RANDOM
-
-long
-QUtil::random()
-{
- static bool seeded_random = false;
- if (! seeded_random)
- {
- // Seed the random number generator with something simple, but
- // just to be interesting, don't use the unmodified current
- // time. It would be better if this were a more secure seed.
- QUtil::srandom(QUtil::get_current_time() ^ 0xcccc);
- seeded_random = true;
- }
-
-# ifdef HAVE_RANDOM
- return ::random();
-# else
- return rand();
-# endif
-}
-
-void
-QUtil::initializeWithRandomBytes(unsigned char* data, size_t len)
-{
- for (size_t i = 0; i < len; ++i)
- {
- data[i] = static_cast<unsigned char>((QUtil::random() & 0xff0) >> 4);
- }
-}
-
-#else
+// Random data support
long
QUtil::random()
@@ -426,66 +398,50 @@ QUtil::random()
return result;
}
-#ifdef _WIN32
-class WindowsCryptProvider
+static RandomDataProvider* random_data_provider = 0;
+
+#ifdef USE_INSECURE_RANDOM
+static RandomDataProvider* insecure_random_data_provider =
+ InsecureRandomDataProvider::getInstance();
+#else
+static RandomDataProvider* insecure_random_data_provider = 0;
+#endif
+static RandomDataProvider* secure_random_data_provider =
+ SecureRandomDataProvider::getInstance();
+
+static void
+initialize_random_data_provider()
{
- public:
- WindowsCryptProvider()
+ if (random_data_provider == 0)
{
- if (! CryptAcquireContext(&crypt_prov, NULL, NULL, PROV_RSA_FULL, 0))
+ if (secure_random_data_provider)
+ {
+ random_data_provider = secure_random_data_provider;
+ }
+ else if (insecure_random_data_provider)
{
- throw std::runtime_error("unable to acquire crypt context");
+ random_data_provider = insecure_random_data_provider;
}
}
- ~WindowsCryptProvider()
+ if (random_data_provider == 0)
{
- // Ignore error
- CryptReleaseContext(crypt_prov, 0);
+ throw std::logic_error("QPDF has no random data provider");
}
+}
- HCRYPTPROV crypt_prov;
-};
-#endif
+void
+QUtil::setRandomDataProvider(RandomDataProvider* p)
+{
+ random_data_provider = p;
+}
void
QUtil::initializeWithRandomBytes(unsigned char* data, size_t len)
{
-#if defined(_WIN32)
-
- // Optimization: make the WindowsCryptProvider static as long as
- // it can be done in a thread-safe fashion.
- WindowsCryptProvider c;
- if (! CryptGenRandom(c.crypt_prov, len, reinterpret_cast<BYTE*>(data)))
- {
- throw std::runtime_error("unable to generate secure random data");
- }
-
-#elif defined(RANDOM_DEVICE)
-
- // Optimization: wrap the file open and close in a class so that
- // the file is closed in a destructor, then make this static to
- // keep the file handle open. Only do this if it can be done in a
- // thread-safe fashion.
- FILE* f = QUtil::safe_fopen(RANDOM_DEVICE, "rb");
- size_t fr = fread(data, 1, len, f);
- fclose(f);
- if (fr != len)
- {
- throw std::runtime_error(
- "unable to read " +
- QUtil::int_to_string(len) +
- " bytes from " + std::string(RANDOM_DEVICE));
- }
-
-#else
-
-# error "Don't know how to generate secure random numbers on this platform. See random number generation in the top-level README"
-
-#endif
+ initialize_random_data_provider();
+ random_data_provider->provideRandomData(data, len);
}
-#endif
-
void
QUtil::srandom(unsigned int seed)
{