diff options
author | lloyd <[email protected]> | 2015-03-18 10:10:09 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2015-03-18 10:10:09 +0000 |
commit | 1c5c28f2e8a605c0429bacd49fc8cacbbb50377a (patch) | |
tree | cd955920104c7d1d3db0cd56af7d350a04124de9 | |
parent | 827080864508e03d796c5138b34d563977d693bb (diff) |
Remove the shared IO buffer from EntropySource_Accumulator.
Instead each source that needs a buffer maintains their own.
-rw-r--r-- | src/lib/entropy/beos_stats/es_beos.cpp | 2 | ||||
-rw-r--r-- | src/lib/entropy/dev_random/dev_random.cpp | 6 | ||||
-rw-r--r-- | src/lib/entropy/dev_random/dev_random.h | 1 | ||||
-rw-r--r-- | src/lib/entropy/egd/es_egd.cpp | 6 | ||||
-rw-r--r-- | src/lib/entropy/egd/es_egd.h | 1 | ||||
-rw-r--r-- | src/lib/entropy/entropy_src.h | 37 | ||||
-rw-r--r-- | src/lib/entropy/entropy_srcs.cpp | 10 | ||||
-rw-r--r-- | src/lib/entropy/proc_walk/proc_walk.cpp | 8 | ||||
-rw-r--r-- | src/lib/entropy/proc_walk/proc_walk.h | 1 | ||||
-rw-r--r-- | src/lib/entropy/rdrand/rdrand.cpp | 24 | ||||
-rw-r--r-- | src/lib/entropy/unix_procs/unix_procs.cpp | 8 | ||||
-rw-r--r-- | src/lib/entropy/unix_procs/unix_procs.h | 1 | ||||
-rw-r--r-- | src/lib/entropy/win32_stats/es_win32.cpp | 6 |
13 files changed, 51 insertions, 60 deletions
diff --git a/src/lib/entropy/beos_stats/es_beos.cpp b/src/lib/entropy/beos_stats/es_beos.cpp index 089bc3a71..c0dfdd89b 100644 --- a/src/lib/entropy/beos_stats/es_beos.cpp +++ b/src/lib/entropy/beos_stats/es_beos.cpp @@ -55,7 +55,7 @@ void BeOS_EntropySource::poll(Entropy_Accumulator& accum) while(get_next_area_info(id, &cookie, &info_area) == B_OK) accum.add(info_area, 2); - if(accum.polling_goal_achieved()) + if(accum.polling_finished()) break; } } diff --git a/src/lib/entropy/dev_random/dev_random.cpp b/src/lib/entropy/dev_random/dev_random.cpp index 7c95fe20d..b115e0da2 100644 --- a/src/lib/entropy/dev_random/dev_random.cpp +++ b/src/lib/entropy/dev_random/dev_random.cpp @@ -81,15 +81,15 @@ void Device_EntropySource::poll(Entropy_Accumulator& accum) if(::select(max_fd + 1, &read_set, nullptr, nullptr, &timeout) < 0) return; - secure_vector<byte>& io_buffer = accum.get_io_buffer(READ_ATTEMPT); + m_buf.resize(READ_ATTEMPT); for(size_t i = 0; i != m_devices.size(); ++i) { if(FD_ISSET(m_devices[i], &read_set)) { - const ssize_t got = ::read(m_devices[i], &io_buffer[0], io_buffer.size()); + const ssize_t got = ::read(m_devices[i], &m_buf[0], m_buf.size()); if(got > 0) - accum.add(&io_buffer[0], got, ENTROPY_BITS_PER_BYTE); + accum.add(&m_buf[0], got, ENTROPY_BITS_PER_BYTE); } } } diff --git a/src/lib/entropy/dev_random/dev_random.h b/src/lib/entropy/dev_random/dev_random.h index 44b02ede0..1df616d56 100644 --- a/src/lib/entropy/dev_random/dev_random.h +++ b/src/lib/entropy/dev_random/dev_random.h @@ -29,6 +29,7 @@ class Device_EntropySource : public EntropySource private: typedef int fd_type; + secure_vector<byte> m_buf; std::vector<fd_type> m_devices; }; diff --git a/src/lib/entropy/egd/es_egd.cpp b/src/lib/entropy/egd/es_egd.cpp index 1595935d2..728104b44 100644 --- a/src/lib/entropy/egd/es_egd.cpp +++ b/src/lib/entropy/egd/es_egd.cpp @@ -141,15 +141,15 @@ void EGD_EntropySource::poll(Entropy_Accumulator& accum) std::lock_guard<std::mutex> lock(m_mutex); - secure_vector<byte>& io_buffer = accum.get_io_buffer(READ_ATTEMPT); + m_buf.resize(READ_ATTEMPT); for(size_t i = 0; i != sockets.size(); ++i) { - size_t got = sockets[i].read(&io_buffer[0], io_buffer.size()); + size_t got = sockets[i].read(&m_buf[0], m_buf.size()); if(got) { - accum.add(&io_buffer[0], got, 6); + accum.add(&m_buf[0], got, 6); break; } } diff --git a/src/lib/entropy/egd/es_egd.h b/src/lib/entropy/egd/es_egd.h index 3f46bc64f..0c9caec66 100644 --- a/src/lib/entropy/egd/es_egd.h +++ b/src/lib/entropy/egd/es_egd.h @@ -44,6 +44,7 @@ class EGD_EntropySource : public EntropySource std::mutex m_mutex; std::vector<EGD_Socket> sockets; + secure_vector<byte> m_buf; }; } diff --git a/src/lib/entropy/entropy_src.h b/src/lib/entropy/entropy_src.h index 2bd7d42e5..c635b8756 100644 --- a/src/lib/entropy/entropy_src.h +++ b/src/lib/entropy/entropy_src.h @@ -1,12 +1,12 @@ /* * EntropySource -* (C) 2008-2009,2014 Jack Lloyd +* (C) 2008,2009,2014,2015 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ -#ifndef BOTAN_ENTROPY_SOURCE_BASE_H__ -#define BOTAN_ENTROPY_SOURCE_BASE_H__ +#ifndef BOTAN_ENTROPY_H__ +#define BOTAN_ENTROPY_H__ #include <botan/secmem.h> #include <string> @@ -22,32 +22,26 @@ class BOTAN_DLL Entropy_Accumulator public: /** * Initialize an Entropy_Accumulator - * @param goal is how many bits we would like to collect + * + * @param accum will be called with poll results, first params the data and + * length, the second a best estimate of min-entropy for the entire buffer; + * out of an abundance of caution this will be zero for many sources. + * accum should return true if it wants the polling to stop, though it may + * still be called again a few more times, and should be careful to return + * true then as well. */ Entropy_Accumulator(std::function<bool (const byte[], size_t, double)> accum) : - m_accum_fn(accum), m_done(false) {} + m_accum_fn(accum) {} virtual ~Entropy_Accumulator() {} /** - * Get a cached I/O buffer (purely for minimizing allocation - * overhead to polls) - * - * @param size requested size for the I/O buffer - * @return cached I/O buffer for repeated polls - */ - secure_vector<byte>& get_io_buffer(size_t size) - { - m_io_buffer.clear(); - m_io_buffer.resize(size); - return m_io_buffer; - } - - /** * @return if our polling goal has been achieved */ bool polling_goal_achieved() const { return m_done; } + bool polling_finished() const { return m_done; } + /** * Add entropy to the accumulator * @param bytes the input bytes @@ -58,7 +52,7 @@ class BOTAN_DLL Entropy_Accumulator void add(const void* bytes, size_t length, double entropy_bits_per_byte) { m_done = m_accum_fn(reinterpret_cast<const byte*>(bytes), - length, entropy_bits_per_byte * length); + length, entropy_bits_per_byte * length) || m_done; } /** @@ -74,8 +68,7 @@ class BOTAN_DLL Entropy_Accumulator } private: std::function<bool (const byte[], size_t, double)> m_accum_fn; - bool m_done; - secure_vector<byte> m_io_buffer; + bool m_done = false; }; /** diff --git a/src/lib/entropy/entropy_srcs.cpp b/src/lib/entropy/entropy_srcs.cpp index 67bced409..d44ab8c92 100644 --- a/src/lib/entropy/entropy_srcs.cpp +++ b/src/lib/entropy/entropy_srcs.cpp @@ -74,8 +74,7 @@ std::vector<std::unique_ptr<EntropySource>> get_default_entropy_sources() #endif #if defined(BOTAN_HAS_ENTROPY_SRC_PROC_WALKER) - sources.push_back(std::unique_ptr<EntropySource>( - new ProcWalking_EntropySource("/proc"))); + sources.push_back(std::unique_ptr<EntropySource>(new ProcWalking_EntropySource("/proc"))); #endif #if defined(BOTAN_HAS_ENTROPY_SRC_WIN32) @@ -87,8 +86,7 @@ std::vector<std::unique_ptr<EntropySource>> get_default_entropy_sources() #endif #if defined(BOTAN_HAS_ENTROPY_SRC_UNIX_PROCESS_RUNNER) - sources.push_back(std::unique_ptr<EntropySource>( - new Unix_EntropySource( + sources.push_back(std::unique_ptr<EntropySource>(new Unix_EntropySource( { "/bin", "/sbin", "/usr/bin", "/usr/sbin" } ))); #endif @@ -110,11 +108,11 @@ void EntropySource::poll_available_sources(class Entropy_Accumulator& accum) static std::vector<std::unique_ptr<EntropySource>> g_sources(get_default_entropy_sources()); if(g_sources.empty()) - throw std::runtime_error("No entropy sources enabled at build time, poll failed"); + throw std::runtime_error("No entropy sources enabled at build time, RNG poll failed"); size_t poll_attempt = 0; - while(!accum.polling_goal_achieved() && poll_attempt < 16) + while(!accum.polling_finished() && poll_attempt < 16) { const size_t src_idx = poll_attempt % g_sources.size(); g_sources[src_idx]->poll(accum); diff --git a/src/lib/entropy/proc_walk/proc_walk.cpp b/src/lib/entropy/proc_walk/proc_walk.cpp index 55affda40..1501f0774 100644 --- a/src/lib/entropy/proc_walk/proc_walk.cpp +++ b/src/lib/entropy/proc_walk/proc_walk.cpp @@ -120,7 +120,7 @@ void ProcWalking_EntropySource::poll(Entropy_Accumulator& accum) if(!m_dir) m_dir.reset(new Directory_Walker(m_path)); - secure_vector<byte>& io_buffer = accum.get_io_buffer(4096); + m_buf.resize(4096); for(size_t i = 0; i != MAX_FILES_READ_PER_POLL; ++i) { @@ -133,13 +133,13 @@ void ProcWalking_EntropySource::poll(Entropy_Accumulator& accum) break; } - ssize_t got = ::read(fd, &io_buffer[0], io_buffer.size()); + ssize_t got = ::read(fd, &m_buf[0], m_buf.size()); ::close(fd); if(got > 0) - accum.add(&io_buffer[0], got, ENTROPY_ESTIMATE); + accum.add(&m_buf[0], got, ENTROPY_ESTIMATE); - if(accum.polling_goal_achieved()) + if(accum.polling_finished()) break; } } diff --git a/src/lib/entropy/proc_walk/proc_walk.h b/src/lib/entropy/proc_walk/proc_walk.h index 079fdc2cd..939feb112 100644 --- a/src/lib/entropy/proc_walk/proc_walk.h +++ b/src/lib/entropy/proc_walk/proc_walk.h @@ -37,6 +37,7 @@ class ProcWalking_EntropySource : public EntropySource const std::string m_path; std::mutex m_mutex; std::unique_ptr<File_Descriptor_Source> m_dir; + secure_vector<byte> m_buf; }; } diff --git a/src/lib/entropy/rdrand/rdrand.cpp b/src/lib/entropy/rdrand/rdrand.cpp index f0782390e..3ae924cde 100644 --- a/src/lib/entropy/rdrand/rdrand.cpp +++ b/src/lib/entropy/rdrand/rdrand.cpp @@ -1,6 +1,6 @@ /* * Entropy Source Using Intel's rdrand instruction -* (C) 2012 Jack Lloyd +* (C) 2012,2015 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -23,20 +23,16 @@ void Intel_Rdrand::poll(Entropy_Accumulator& accum) return; /* - * Put an upper bound on the total entropy we're willing to claim - * for any one polling of rdrand to prevent it from swamping our - * poll. Internally, the rdrand system is a DRGB that reseeds at a - * somewhat unpredictable rate (the current conditions are - * documented, but that might not be true for different - * implementations, eg on Haswell or a future AMD chip, so I don't - * want to assume). This limit ensures we're going to poll at least - * one other source so we have some diversity in our inputs. - */ + Don't consider rdrand as contributing any entropy to the poll. It doesn't + make sense to trust uninspectible hardware. - const size_t POLL_UPPER_BOUND = 96; + Even if backdoored, rdrand cannot harm us because the HMAC_RNG poll process + is designed to handle arbitrarily large amounts of attacker known/chosen + input (or even a reseed where every bit we reseeded with was attacker chosen), + as long as at least one seed occured with enough unknown-to-attacker entropy. + */ + const double ENTROPY_ESTIMATE = 0.0; const size_t RDRAND_POLLS = 32; - const double ENTROPY_PER_POLL = - static_cast<double>(POLL_UPPER_BOUND) / (RDRAND_POLLS * 4); for(size_t i = 0; i != RDRAND_POLLS; ++i) { @@ -53,7 +49,7 @@ void Intel_Rdrand::poll(Entropy_Accumulator& accum) #endif if(cf == 1) - accum.add(r, ENTROPY_PER_POLL); + accum.add(r, ENTROPY_ESTIMATE); } } diff --git a/src/lib/entropy/unix_procs/unix_procs.cpp b/src/lib/entropy/unix_procs/unix_procs.cpp index f7583cf23..1cc93741c 100644 --- a/src/lib/entropy/unix_procs/unix_procs.cpp +++ b/src/lib/entropy/unix_procs/unix_procs.cpp @@ -213,9 +213,9 @@ void Unix_EntropySource::poll(Entropy_Accumulator& accum) const size_t MS_WAIT_TIME = 32; const double ENTROPY_ESTIMATE = 1.0 / 1024; - secure_vector<byte>& io_buffer = accum.get_io_buffer(4*1024); // page + m_buf.resize(4096); - while(!accum.polling_goal_achieved()) + while(!accum.polling_finished()) { while(m_procs.size() < m_concurrent) m_procs.emplace_back(Unix_Process(next_source())); @@ -253,9 +253,9 @@ void Unix_EntropySource::poll(Entropy_Accumulator& accum) if(FD_ISSET(fd, &read_set)) { - const ssize_t got = ::read(fd, &io_buffer[0], io_buffer.size()); + const ssize_t got = ::read(fd, &m_buf[0], m_buf.size()); if(got > 0) - accum.add(&io_buffer[0], got, ENTROPY_ESTIMATE); + accum.add(&m_buf[0], got, ENTROPY_ESTIMATE); else proc.spawn(next_source()); } diff --git a/src/lib/entropy/unix_procs/unix_procs.h b/src/lib/entropy/unix_procs/unix_procs.h index eb798b207..cf6a8bb7d 100644 --- a/src/lib/entropy/unix_procs/unix_procs.h +++ b/src/lib/entropy/unix_procs/unix_procs.h @@ -75,6 +75,7 @@ class Unix_EntropySource : public EntropySource size_t m_sources_idx = 0; std::vector<Unix_Process> m_procs; + secure_vector<byte> m_buf; }; class UnixProcessInfo_EntropySource : public EntropySource diff --git a/src/lib/entropy/win32_stats/es_win32.cpp b/src/lib/entropy/win32_stats/es_win32.cpp index f57c4bebb..04e441570 100644 --- a/src/lib/entropy/win32_stats/es_win32.cpp +++ b/src/lib/entropy/win32_stats/es_win32.cpp @@ -54,7 +54,7 @@ void Win32_EntropySource::poll(Entropy_Accumulator& accum) HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0); #define TOOLHELP32_ITER(DATA_TYPE, FUNC_FIRST, FUNC_NEXT) \ - if(!accum.polling_goal_achieved()) \ + if(!accum.polling_finished()) \ { \ DATA_TYPE info; \ info.dwSize = sizeof(DATA_TYPE); \ @@ -73,7 +73,7 @@ void Win32_EntropySource::poll(Entropy_Accumulator& accum) #undef TOOLHELP32_ITER - if(!accum.polling_goal_achieved()) + if(!accum.polling_finished()) { size_t heap_lists_found = 0; HEAPLIST32 heap_list; @@ -105,7 +105,7 @@ void Win32_EntropySource::poll(Entropy_Accumulator& accum) } while(Heap32Next(&heap_entry)); } - if(accum.polling_goal_achieved()) + if(accum.polling_finished()) break; } while(Heap32ListNext(snapshot, &heap_list)); |