From d0c2f90af8df600204636a701f8f279c17d6959c Mon Sep 17 00:00:00 2001 From: lloyd Date: Mon, 27 Oct 2008 17:05:12 +0000 Subject: Substantially change Randpool's reseed logic. Now when a reseed is requested, Randpool will first do a fast poll on each entropy source that has been registered. It will count these poll results towards the collected entropy count, with a maximum of 96 contributed bits of entropy per poll (only /dev/random reaches this, others measure at 50-60 bits typically), and a maximum of 256 for sum contribution of the fast polls. Then it will attempt slow polls of all devices until it thinks enough entropy has been collected (using the rather naive entropy_estimate function). It will count any slow poll for no more than 256 bits (100 or so is typical for every poll but /dev/random), and will attempt to collect at least 512 bits of (estimated/guessed) entropy. This tends to cause Randpool to use significantly more sources. Previously it was common, especially on systems with a /dev/random, for only one or a few sources to be used. This change helps assure that even if /dev/random and company are broken or compromised the RNG output remains secure (assuming at least some amount of entropy unguessable by the attacker can be collected via other sources). Also change AutoSeeded_RNG do an automatic poll/seed when it is created. --- src/entropy/beos_stats/es_beos.h | 2 ++ src/entropy/buf_es/buf_es.cpp | 6 +--- src/entropy/cryptoapi_rng/es_capi.h | 2 ++ src/entropy/dev_random/es_dev.cpp | 2 +- src/entropy/dev_random/es_dev.h | 2 ++ src/entropy/egd/es_egd.cpp | 4 +-- src/entropy/egd/es_egd.h | 2 ++ src/entropy/entropy_src.h | 3 ++ src/entropy/proc_walk/es_ftw.cpp | 32 ++++++++++++++---- src/entropy/proc_walk/es_ftw.h | 11 ++++++ src/entropy/unix_procs/es_unix.cpp | 2 +- src/entropy/unix_procs/es_unix.h | 2 ++ src/entropy/win32_stats/es_win32.h | 1 + src/rng/auto_rng/auto_rng.cpp | 45 ++++++++++++++++--------- src/rng/randpool/randpool.cpp | 21 ++++++++++-- src/utils/timer/cpu_counter/tm_hard.h | 1 + src/utils/timer/gettimeofday/tm_unix.h | 1 + src/utils/timer/posix_rt/tm_posix.h | 1 + src/utils/timer/win32_query_perf_ctr/tm_win32.h | 1 + 19 files changed, 107 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/entropy/beos_stats/es_beos.h b/src/entropy/beos_stats/es_beos.h index 57e15c9d9..ec461780d 100644 --- a/src/entropy/beos_stats/es_beos.h +++ b/src/entropy/beos_stats/es_beos.h @@ -16,6 +16,8 @@ namespace Botan { class BOTAN_DLL BeOS_EntropySource : public Buffered_EntropySource { private: + std::string name() const { return "BeOS Statistics"; } + void do_fast_poll(); void do_slow_poll(); }; diff --git a/src/entropy/buf_es/buf_es.cpp b/src/entropy/buf_es/buf_es.cpp index 19f30e22c..4a88d67bd 100644 --- a/src/entropy/buf_es/buf_es.cpp +++ b/src/entropy/buf_es/buf_es.cpp @@ -13,10 +13,9 @@ namespace Botan { /************************************************* * Buffered_EntropySource Constructor * *************************************************/ -Buffered_EntropySource::Buffered_EntropySource() : buffer(256) +Buffered_EntropySource::Buffered_EntropySource() : buffer(128) { read_pos = write_pos = 0; - done_slow_poll = false; } /************************************************* @@ -24,8 +23,6 @@ Buffered_EntropySource::Buffered_EntropySource() : buffer(256) *************************************************/ u32bit Buffered_EntropySource::fast_poll(byte out[], u32bit length) { - if(!done_slow_poll) { do_slow_poll(); done_slow_poll = true; } - do_fast_poll(); return copy_out(out, length, buffer.size() / 4); } @@ -36,7 +33,6 @@ u32bit Buffered_EntropySource::fast_poll(byte out[], u32bit length) u32bit Buffered_EntropySource::slow_poll(byte out[], u32bit length) { do_slow_poll(); - done_slow_poll = true; return copy_out(out, length, buffer.size()); } diff --git a/src/entropy/cryptoapi_rng/es_capi.h b/src/entropy/cryptoapi_rng/es_capi.h index 73d9ae1c2..c8f83427c 100644 --- a/src/entropy/cryptoapi_rng/es_capi.h +++ b/src/entropy/cryptoapi_rng/es_capi.h @@ -17,6 +17,8 @@ namespace Botan { class BOTAN_DLL Win32_CAPI_EntropySource : public EntropySource { public: + std::string name() const { return "Win32 CryptoGenRandom"; } + u32bit slow_poll(byte[], u32bit); Win32_CAPI_EntropySource(const std::string& = ""); private: diff --git a/src/entropy/dev_random/es_dev.cpp b/src/entropy/dev_random/es_dev.cpp index 426ef8443..04b3a90ee 100644 --- a/src/entropy/dev_random/es_dev.cpp +++ b/src/entropy/dev_random/es_dev.cpp @@ -114,7 +114,7 @@ u32bit Device_EntropySource::slow_poll(byte output[], u32bit length) */ u32bit Device_EntropySource::fast_poll(byte output[], u32bit length) { - return slow_poll(output, std::max(length, 64)); + return slow_poll(output, std::min(length, 64)); } } diff --git a/src/entropy/dev_random/es_dev.h b/src/entropy/dev_random/es_dev.h index 024afbdb4..2c9d93369 100644 --- a/src/entropy/dev_random/es_dev.h +++ b/src/entropy/dev_random/es_dev.h @@ -18,6 +18,8 @@ namespace Botan { class BOTAN_DLL Device_EntropySource : public EntropySource { public: + std::string name() const { return "RNG Device Reader"; } + Device_EntropySource(const std::vector& fs) : fsnames(fs) {} diff --git a/src/entropy/egd/es_egd.cpp b/src/entropy/egd/es_egd.cpp index 8390552c6..41c7d29f2 100644 --- a/src/entropy/egd/es_egd.cpp +++ b/src/entropy/egd/es_egd.cpp @@ -75,11 +75,11 @@ u32bit EGD_EntropySource::slow_poll(byte output[], u32bit length) } /** -* Gather Entropy from EGD, limiting to 32 bytes +* Gather Entropy from EGD, limiting to 64 bytes */ u32bit EGD_EntropySource::fast_poll(byte output[], u32bit length) { - return slow_poll(output, std::max(length, 64)); + return slow_poll(output, std::min(length, 64)); } } diff --git a/src/entropy/egd/es_egd.h b/src/entropy/egd/es_egd.h index 4f1eb9127..ca2e97349 100644 --- a/src/entropy/egd/es_egd.h +++ b/src/entropy/egd/es_egd.h @@ -18,6 +18,8 @@ namespace Botan { class BOTAN_DLL EGD_EntropySource : public EntropySource { public: + std::string name() const { return "EGD/PRNGD"; } + u32bit fast_poll(byte[], u32bit); u32bit slow_poll(byte[], u32bit); diff --git a/src/entropy/entropy_src.h b/src/entropy/entropy_src.h index 4ee24ce4a..0891e393f 100644 --- a/src/entropy/entropy_src.h +++ b/src/entropy/entropy_src.h @@ -7,6 +7,7 @@ #define BOTAN_ENTROPY_SOURCE_BASE_H__ #include +#include namespace Botan { @@ -16,6 +17,8 @@ namespace Botan { class BOTAN_DLL EntropySource { public: + virtual std::string name() const = 0; + virtual u32bit slow_poll(byte buf[], u32bit len) = 0; virtual u32bit fast_poll(byte buf[], u32bit len) = 0; virtual ~EntropySource() {} diff --git a/src/entropy/proc_walk/es_ftw.cpp b/src/entropy/proc_walk/es_ftw.cpp index ec11378f8..f90d422a5 100644 --- a/src/entropy/proc_walk/es_ftw.cpp +++ b/src/entropy/proc_walk/es_ftw.cpp @@ -22,7 +22,7 @@ namespace Botan { namespace { -class Directory_Walker +class Directory_Walker : public FTW_EntropySource::File_Descriptor_Source { public: Directory_Walker(const std::string& root) { add_directory(root); } @@ -93,11 +93,20 @@ int Directory_Walker::next_fd() } -/************************************************* -* FTW_EntropySource Constructor * -*************************************************/ +/** +* FTW_EntropySource Constructor +*/ FTW_EntropySource::FTW_EntropySource(const std::string& p) : path(p) { + dir = 0; + } + +/** +* FTW_EntropySource Destructor +*/ +FTW_EntropySource::~FTW_EntropySource() + { + delete dir; } /************************************************* @@ -121,16 +130,25 @@ void FTW_EntropySource::do_slow_poll() *************************************************/ void FTW_EntropySource::poll(u32bit max_read) { - Directory_Walker dir(path); + if(!dir) + dir = new Directory_Walker(path); + SecureVector read_buf(1024); u32bit read_so_far = 0; while(read_so_far < max_read) { - int fd = dir.next_fd(); + int fd = dir->next_fd(); if(fd == -1) - break; + { + delete dir; + dir = new Directory_Walker(path); + fd = dir->next_fd(); + + if(fd == -1) // still fails (directory not mounted, etc) -> exit + break; + } ssize_t got = ::read(fd, read_buf.begin(), read_buf.size()); diff --git a/src/entropy/proc_walk/es_ftw.h b/src/entropy/proc_walk/es_ftw.h index e0d266141..a0d480aae 100644 --- a/src/entropy/proc_walk/es_ftw.h +++ b/src/entropy/proc_walk/es_ftw.h @@ -16,7 +16,17 @@ namespace Botan { class BOTAN_DLL FTW_EntropySource : public Buffered_EntropySource { public: + std::string name() const { return "Proc Walker"; } + FTW_EntropySource(const std::string& root_dir); + ~FTW_EntropySource(); + + class File_Descriptor_Source + { + public: + virtual int next_fd() = 0; + virtual ~File_Descriptor_Source() {} + }; private: void do_fast_poll(); void do_slow_poll(); @@ -24,6 +34,7 @@ class BOTAN_DLL FTW_EntropySource : public Buffered_EntropySource void poll(u32bit max_read); const std::string path; + File_Descriptor_Source* dir; }; } diff --git a/src/entropy/unix_procs/es_unix.cpp b/src/entropy/unix_procs/es_unix.cpp index c503c20ae..012a38ce0 100644 --- a/src/entropy/unix_procs/es_unix.cpp +++ b/src/entropy/unix_procs/es_unix.cpp @@ -47,7 +47,7 @@ void Unix_EntropySource::add_sources(const Unix_Program srcs[], u32bit count) *************************************************/ void Unix_EntropySource::do_fast_poll() { - const char* STAT_TARGETS[] = { "/", "/tmp", ".", "..", 0 }; + const char* STAT_TARGETS[] = { "/", "/tmp", "/etc/passwd", ".", "..", 0 }; for(u32bit j = 0; STAT_TARGETS[j]; j++) { diff --git a/src/entropy/unix_procs/es_unix.h b/src/entropy/unix_procs/es_unix.h index 4925fd4e1..907ebbc3a 100644 --- a/src/entropy/unix_procs/es_unix.h +++ b/src/entropy/unix_procs/es_unix.h @@ -18,6 +18,8 @@ namespace Botan { class BOTAN_DLL Unix_EntropySource : public Buffered_EntropySource { public: + std::string name() const { return "Unix Entropy Source"; } + void add_sources(const Unix_Program[], u32bit); Unix_EntropySource(const std::vector& path); private: diff --git a/src/entropy/win32_stats/es_win32.h b/src/entropy/win32_stats/es_win32.h index f2314ab0c..1fd07df1d 100644 --- a/src/entropy/win32_stats/es_win32.h +++ b/src/entropy/win32_stats/es_win32.h @@ -16,6 +16,7 @@ namespace Botan { class BOTAN_DLL Win32_EntropySource : public Buffered_EntropySource { private: + std::string name() const { return "Win32 Statistics"; } void do_fast_poll(); void do_slow_poll(); }; diff --git a/src/rng/auto_rng/auto_rng.cpp b/src/rng/auto_rng/auto_rng.cpp index 076630f6d..51d71f7d0 100644 --- a/src/rng/auto_rng/auto_rng.cpp +++ b/src/rng/auto_rng/auto_rng.cpp @@ -17,11 +17,17 @@ #if defined(BOTAN_HAS_TIMER_HARDWARE) #include -#elif defined(BOTAN_HAS_TIMER_POSIX) +#endif + +#if defined(BOTAN_HAS_TIMER_POSIX) #include -#elif defined(BOTAN_HAS_TIMER_UNIX) +#endif + +#if defined(BOTAN_HAS_TIMER_UNIX) #include -#elif defined(BOTAN_HAS_TIMER_WIN32) +#endif + +#if defined(BOTAN_HAS_TIMER_WIN32) #include #endif @@ -64,14 +70,18 @@ void add_entropy_sources(RandomNumberGenerator* rng) { #if defined(BOTAN_HAS_TIMER_HARDWARE) rng->add_entropy_source(new Hardware_Timer); -#elif defined(BOTAN_HAS_TIMER_POSIX) +#endif + +#if defined(BOTAN_HAS_TIMER_POSIX) rng->add_entropy_source(new POSIX_Timer); -#elif defined(BOTAN_HAS_TIMER_UNIX) +#endif + +#if defined(BOTAN_HAS_TIMER_UNIX) rng->add_entropy_source(new Unix_Timer); -#elif defined(BOTAN_HAS_TIMER_WIN32) +#endif + +#if defined(BOTAN_HAS_TIMER_WIN32) rng->add_entropy_source(new Win32_Timer); -#else - rng->add_entropy_source(new Timer); #endif #if defined(BOTAN_HAS_ENTROPY_SRC_DEVICE) @@ -92,22 +102,23 @@ void add_entropy_sources(RandomNumberGenerator* rng) rng->add_entropy_source(new Win32_CAPI_EntropySource); #endif -#if defined(BOTAN_HAS_ENTROPY_SRC_WIN32) - rng->add_entropy_source(new Win32_EntropySource); +#if defined(BOTAN_HAS_ENTROPY_SRC_FTW) + rng->add_entropy_source(new FTW_EntropySource("/proc")); #endif -#if defined(BOTAN_HAS_ENTROPY_SRC_UNIX) - rng->add_entropy_source( - new Unix_EntropySource(split_on("/bin:/sbin:/usr/bin:/usr/sbin", ':')) - ); + +#if defined(BOTAN_HAS_ENTROPY_SRC_WIN32) + rng->add_entropy_source(new Win32_EntropySource); #endif #if defined(BOTAN_HAS_ENTROPY_SRC_BEOS) rng->add_entropy_source(new BeOS_EntropySource); #endif -#if defined(BOTAN_HAS_ENTROPY_SRC_FTW) - rng->add_entropy_source(new FTW_EntropySource("/proc")); +#if defined(BOTAN_HAS_ENTROPY_SRC_UNIX) + rng->add_entropy_source( + new Unix_EntropySource(split_on("/bin:/sbin:/usr/bin:/usr/sbin", ':')) + ); #endif } @@ -124,6 +135,8 @@ AutoSeeded_RNG::AutoSeeded_RNG() #endif add_entropy_sources(rng); + + rng->reseed(); } } diff --git a/src/rng/randpool/randpool.cpp b/src/rng/randpool/randpool.cpp index d7d1763ec..dd80a7f70 100644 --- a/src/rng/randpool/randpool.cpp +++ b/src/rng/randpool/randpool.cpp @@ -106,16 +106,33 @@ void Randpool::mix_pool() *************************************************/ void Randpool::reseed() { - SecureVector buffer(1024); + SecureVector buffer(128); + u32bit gathered_entropy = 0; + // First do a fast poll of all sources (no matter what) + for(u32bit j = 0; j != entropy_sources.size(); ++j) + { + u32bit got = entropy_sources[j]->fast_poll(buffer, buffer.size()); + u32bit entropy = std::min(96, entropy_estimate(buffer, got)); + + mac->update(buffer, got); + + gathered_entropy += entropy; + } + + // Limit assumed entropy from fast polls to 256 bits total + gathered_entropy = std::min(256, gathered_entropy); + + // Then do a slow poll, until we think we have got enough entropy for(u32bit j = 0; j != entropy_sources.size(); ++j) { u32bit got = entropy_sources[j]->slow_poll(buffer, buffer.size()); + u32bit entropy = std::min(256, entropy_estimate(buffer, got)); mac->update(buffer, got); - gathered_entropy += entropy_estimate(buffer, got); + gathered_entropy += entropy; if(gathered_entropy > 512) break; } diff --git a/src/utils/timer/cpu_counter/tm_hard.h b/src/utils/timer/cpu_counter/tm_hard.h index 1ed100bad..436cec22c 100644 --- a/src/utils/timer/cpu_counter/tm_hard.h +++ b/src/utils/timer/cpu_counter/tm_hard.h @@ -16,6 +16,7 @@ namespace Botan { class BOTAN_DLL Hardware_Timer : public Timer { public: + std::string name() const { return "Hardware Timer"; } u64bit clock() const; }; diff --git a/src/utils/timer/gettimeofday/tm_unix.h b/src/utils/timer/gettimeofday/tm_unix.h index 65c86b396..1b6c935a3 100644 --- a/src/utils/timer/gettimeofday/tm_unix.h +++ b/src/utils/timer/gettimeofday/tm_unix.h @@ -16,6 +16,7 @@ namespace Botan { class BOTAN_DLL Unix_Timer : public Timer { public: + std::string name() const { return "Unix gettimeofday"; } u64bit clock() const; }; diff --git a/src/utils/timer/posix_rt/tm_posix.h b/src/utils/timer/posix_rt/tm_posix.h index 7393646e1..0aee67abb 100644 --- a/src/utils/timer/posix_rt/tm_posix.h +++ b/src/utils/timer/posix_rt/tm_posix.h @@ -16,6 +16,7 @@ namespace Botan { class BOTAN_DLL POSIX_Timer : public Timer { public: + std::string name() const { return "POSIX clock_gettime"; } u64bit clock() const; }; diff --git a/src/utils/timer/win32_query_perf_ctr/tm_win32.h b/src/utils/timer/win32_query_perf_ctr/tm_win32.h index 09f30de4b..916bf2127 100644 --- a/src/utils/timer/win32_query_perf_ctr/tm_win32.h +++ b/src/utils/timer/win32_query_perf_ctr/tm_win32.h @@ -16,6 +16,7 @@ namespace Botan { class BOTAN_DLL Win32_Timer : public Timer { public: + std::string name() const { return "Win32 QueryPerformanceCounter"; } u64bit clock() const; }; -- cgit v1.2.3