aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlloyd <[email protected]>2015-03-18 10:10:09 +0000
committerlloyd <[email protected]>2015-03-18 10:10:09 +0000
commit1c5c28f2e8a605c0429bacd49fc8cacbbb50377a (patch)
treecd955920104c7d1d3db0cd56af7d350a04124de9
parent827080864508e03d796c5138b34d563977d693bb (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.cpp2
-rw-r--r--src/lib/entropy/dev_random/dev_random.cpp6
-rw-r--r--src/lib/entropy/dev_random/dev_random.h1
-rw-r--r--src/lib/entropy/egd/es_egd.cpp6
-rw-r--r--src/lib/entropy/egd/es_egd.h1
-rw-r--r--src/lib/entropy/entropy_src.h37
-rw-r--r--src/lib/entropy/entropy_srcs.cpp10
-rw-r--r--src/lib/entropy/proc_walk/proc_walk.cpp8
-rw-r--r--src/lib/entropy/proc_walk/proc_walk.h1
-rw-r--r--src/lib/entropy/rdrand/rdrand.cpp24
-rw-r--r--src/lib/entropy/unix_procs/unix_procs.cpp8
-rw-r--r--src/lib/entropy/unix_procs/unix_procs.h1
-rw-r--r--src/lib/entropy/win32_stats/es_win32.cpp6
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));