aboutsummaryrefslogtreecommitdiffstats
path: root/src/entropy
diff options
context:
space:
mode:
Diffstat (limited to 'src/entropy')
-rw-r--r--src/entropy/beos_stats/es_beos.cpp43
-rw-r--r--src/entropy/beos_stats/es_beos.h3
-rw-r--r--src/entropy/cryptoapi_rng/es_capi.cpp107
-rw-r--r--src/entropy/cryptoapi_rng/es_capi.h9
-rw-r--r--src/entropy/dev_random/es_dev.cpp48
-rw-r--r--src/entropy/dev_random/es_dev.h16
-rw-r--r--src/entropy/egd/es_egd.cpp128
-rw-r--r--src/entropy/egd/es_egd.h10
-rw-r--r--src/entropy/entropy_acc.cpp87
-rw-r--r--src/entropy/entropy_src.h49
-rw-r--r--src/entropy/info.txt1
-rw-r--r--src/entropy/proc_walk/es_ftw.cpp42
-rw-r--r--src/entropy/proc_walk/es_ftw.h9
-rw-r--r--src/entropy/unix_procs/es_unix.cpp99
-rw-r--r--src/entropy/unix_procs/es_unix.h20
-rw-r--r--src/entropy/unix_procs/unix_cmd.cpp74
-rw-r--r--src/entropy/unix_procs/unix_cmd.h20
-rw-r--r--src/entropy/unix_procs/unix_src.cpp14
-rw-r--r--src/entropy/win32_stats/es_win32.cpp167
-rw-r--r--src/entropy/win32_stats/es_win32.h6
20 files changed, 510 insertions, 442 deletions
diff --git a/src/entropy/beos_stats/es_beos.cpp b/src/entropy/beos_stats/es_beos.cpp
index b5a5e7fee..d7c0c6cd6 100644
--- a/src/entropy/beos_stats/es_beos.cpp
+++ b/src/entropy/beos_stats/es_beos.cpp
@@ -4,7 +4,6 @@
*/
#include <botan/es_beos.h>
-#include <botan/xor_buf.h>
#include <kernel/OS.h>
#include <kernel/image.h>
@@ -13,69 +12,49 @@
namespace Botan {
/**
-* BeOS Fast Poll
+* BeOS entropy poll
*/
-u32bit BeOS_EntropySource::fast_poll(byte buf[], u32bit length)
+void BeOS_EntropySource::poll(Entropy_Accumulator& accum)
{
- if(length == 0)
- return 0;
- length = std::min<u32bit>(length, 32);
-
- u32bit buf_i = 0;
-
system_info info_sys;
get_system_info(&info_sys);
- buf_i = xor_into_buf(buf, buf_i, length, info_sys);
+ accum.add(info_sys, 2);
- key_info info_key;
+ key_info info_key; // current state of the keyboard
get_key_info(&info_key);
- buf_i = xor_into_buf(buf, buf_i, length, key_info);
+ accum.add(info_key, 0);
- buf_i = xor_into_buf(buf, buf_i, length, idle_time());
+ accum.add(idle_time(), 0);
- return length;
- }
-
-/**
-* BeOS slow poll
-*/
-u32bit BeOS_EntropySource::slow_poll(byte buf[], u32bit length)
- {
- if(length == 0)
- return 0;
-
- u32bit buf_i = 0;
team_info info_team;
int32 cookie_team = 0;
while(get_next_team_info(&cookie_team, &info_team) == B_OK)
{
- buf_i = xor_into_buf(buf, buf_i, length, info_team);
+ accum.add(info_team, 2);
team_id id = info_team.team;
int32 cookie = 0;
thread_info info_thr;
while(get_next_thread_info(id, &cookie, &info_thr) == B_OK)
- buf_i = xor_into_buf(buf, buf_i, length, info_thr);
+ accum.add(info_thr, 1);
cookie = 0;
image_info info_img;
while(get_next_image_info(id, &cookie, &info_img) == B_OK)
- buf_i = xor_into_buf(buf, buf_i, length, info_img);
+ accum.add(info_img, 1);
cookie = 0;
sem_info info_sem;
while(get_next_sem_info(id, &cookie, &info_sem) == B_OK)
- buf_i = xor_into_buf(buf, buf_i, length, info_sem);
+ accum.add(info_sem, 1);
cookie = 0;
area_info info_area;
while(get_next_area_info(id, &cookie, &info_area) == B_OK)
- buf_i = xor_into_buf(buf, buf_i, length, info_area);
+ accum.add(info_area, 2);
}
-
- return length;
}
}
diff --git a/src/entropy/beos_stats/es_beos.h b/src/entropy/beos_stats/es_beos.h
index 686ac5c38..0ae670e94 100644
--- a/src/entropy/beos_stats/es_beos.h
+++ b/src/entropy/beos_stats/es_beos.h
@@ -18,8 +18,7 @@ class BOTAN_DLL BeOS_EntropySource : public EntropySource
private:
std::string name() const { return "BeOS Statistics"; }
- u32bit fast_poll(byte buf[], u32bit length);
- u32bit slow_poll(byte buf[], u32bit length);
+ void poll(Entropy_Accumulator& accum);
};
}
diff --git a/src/entropy/cryptoapi_rng/es_capi.cpp b/src/entropy/cryptoapi_rng/es_capi.cpp
index ca0e1b95e..7cc4d015b 100644
--- a/src/entropy/cryptoapi_rng/es_capi.cpp
+++ b/src/entropy/cryptoapi_rng/es_capi.cpp
@@ -1,7 +1,7 @@
-/*************************************************
-* Win32 CryptoAPI EntropySource Source File *
-* (C) 1999-2007 Jack Lloyd *
-*************************************************/
+/*
+* Win32 CryptoAPI EntropySource
+* (C) 1999-2009 Jack Lloyd
+*/
#include <botan/es_capi.h>
#include <botan/parsing.h>
@@ -10,71 +10,68 @@
namespace Botan {
-/**
-* Gather Entropy from Win32 CAPI
-*/
-u32bit Win32_CAPI_EntropySource::slow_poll(byte output[], u32bit length)
+namespace {
+
+class CSP_Handle
{
- return fast_poll(output, length);
- }
+ public:
+ CSP_Handle(u64bit capi_provider)
+ {
+ valid = false;
+ DWORD prov_type = (DWORD)capi_provider;
+
+ if(CryptAcquireContext(&handle, 0, 0,
+ prov_type, CRYPT_VERIFYCONTEXT))
+ valid = true;
+ }
+
+ ~CSP_Handle()
+ {
+ if(is_valid())
+ CryptReleaseContext(handle, 0);
+ }
+
+ u32bit gen_random(byte out[], u32bit n) const
+ {
+ if(is_valid() && CryptGenRandom(handle, n, out))
+ return n;
+ return 0;
+ }
+
+ bool is_valid() const { return valid; }
+
+ HCRYPTPROV get_handle() const { return handle; }
+ private:
+ HCRYPTPROV handle;
+ bool valid;
+ };
+
+}
/**
* Gather Entropy from Win32 CAPI
*/
-u32bit Win32_CAPI_EntropySource::fast_poll(byte output[], u32bit length)
+void Win32_CAPI_EntropySource::poll(Entropy_Accumulator& accum)
{
- class CSP_Handle
- {
- public:
- CSP_Handle(u64bit capi_provider)
- {
- valid = false;
- DWORD prov_type = (DWORD)capi_provider;
-
- if(CryptAcquireContext(&handle, 0, 0,
- prov_type, CRYPT_VERIFYCONTEXT))
- valid = true;
- }
-
- ~CSP_Handle()
- {
- if(is_valid())
- CryptReleaseContext(handle, 0);
- }
-
- void gen_random(byte out[], u32bit n) const
- {
- if(is_valid())
- CryptGenRandom(handle, n, out);
- }
-
- bool is_valid() const { return valid; }
-
- HCRYPTPROV get_handle() const { return handle; }
- private:
- HCRYPTPROV handle;
- bool valid;
- };
-
-
- if(length > 64)
- length = 64;
+ MemoryRegion<byte>& io_buffer = accum.get_io_buffer(32);
for(u32bit j = 0; j != prov_types.size(); ++j)
{
CSP_Handle csp(prov_types[j]);
- if(!csp.is_valid())
- continue;
- csp.gen_random(output, length);
- break;
+ u32bit got = csp.gen_random(io_buffer.begin(), io_buffer.length());
+
+ if(got)
+ {
+ accum.add(io_buffer.begin(), io_buffer.length(), 8);
+ break;
+ }
}
- return length;
}
-/*************************************************
-* Gather Entropy from Win32 CAPI *
-*************************************************/
+/**
+* Win32_Capi_Entropysource Constructor
+*/
Win32_CAPI_EntropySource::Win32_CAPI_EntropySource(const std::string& provs)
{
std::vector<std::string> capi_provs = split_on(provs, ':');
diff --git a/src/entropy/cryptoapi_rng/es_capi.h b/src/entropy/cryptoapi_rng/es_capi.h
index b8bbb7507..d727de5dd 100644
--- a/src/entropy/cryptoapi_rng/es_capi.h
+++ b/src/entropy/cryptoapi_rng/es_capi.h
@@ -11,16 +11,15 @@
namespace Botan {
-/*************************************************
-* Win32 CAPI Entropy Source *
-*************************************************/
+/**
+* Win32 CAPI Entropy Source
+*/
class BOTAN_DLL Win32_CAPI_EntropySource : public EntropySource
{
public:
std::string name() const { return "Win32 CryptoGenRandom"; }
- u32bit fast_poll(byte[], u32bit);
- u32bit slow_poll(byte[], u32bit);
+ void poll(Entropy_Accumulator& accum);
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 7b936dbaa..60e1a4df6 100644
--- a/src/entropy/dev_random/es_dev.cpp
+++ b/src/entropy/dev_random/es_dev.cpp
@@ -1,7 +1,7 @@
-/*************************************************
-* Device EntropySource Source File *
-* (C) 1999-2008 Jack Lloyd *
-*************************************************/
+/*
+* /dev/random EntropySource
+* (C) 1999-2009 Jack Lloyd
+*/
#include <botan/es_dev.h>
@@ -79,6 +79,7 @@ Device_EntropySource::Device_Reader::open(const std::string& pathname)
/**
Device_EntropySource constructor
+Open a file descriptor to each (available) device in fsnames
*/
Device_EntropySource::Device_EntropySource(
const std::vector<std::string>& fsnames)
@@ -92,41 +93,36 @@ Device_EntropySource::Device_EntropySource(
}
/**
-* Gather entropy from a RNG device
+Device_EntropySource destructor: close all open devices
*/
-u32bit Device_EntropySource::slow_poll(byte output[], u32bit length)
+Device_EntropySource::~Device_EntropySource()
{
for(size_t i = 0; i != devices.size(); ++i)
- {
- const u32bit got = devices[i].get(output, length, 20);
-
- if(got)
- return got;
- }
-
- return 0;
+ devices[i].close();
}
/**
-* Fast poll: try limit to 10 ms wait
+* Gather entropy from a RNG device
*/
-u32bit Device_EntropySource::fast_poll(byte output[], u32bit length)
+void Device_EntropySource::poll(Entropy_Accumulator& accum)
{
+ const u32bit MAX_READ_WAIT_MILLISECONDS = 50;
+
+ u32bit go_get = std::min<u32bit>(accum.desired_remaining_bits() / 8, 32);
+
+ MemoryRegion<byte>& io_buffer = accum.get_io_buffer(go_get);
+
for(size_t i = 0; i != devices.size(); ++i)
{
- const u32bit got = devices[i].get(output, length, 5);
+ u32bit got = devices[i].get(io_buffer.begin(), io_buffer.size(),
+ MAX_READ_WAIT_MILLISECONDS);
if(got)
- return got;
+ {
+ accum.add(io_buffer.begin(), got, 8);
+ break;
+ }
}
-
- return 0;
- }
-
-Device_EntropySource::~Device_EntropySource()
- {
- for(size_t i = 0; i != devices.size(); ++i)
- devices[i].close();
}
}
diff --git a/src/entropy/dev_random/es_dev.h b/src/entropy/dev_random/es_dev.h
index db64b75fa..139f8ec52 100644
--- a/src/entropy/dev_random/es_dev.h
+++ b/src/entropy/dev_random/es_dev.h
@@ -1,7 +1,7 @@
-/*************************************************
-* Device EntropySource Header File *
-* (C) 1999-2007 Jack Lloyd *
-*************************************************/
+/*
+* /dev/random EntropySource
+* (C) 1999-2009 Jack Lloyd
+*/
#ifndef BOTAN_ENTROPY_SRC_DEVICE_H__
#define BOTAN_ENTROPY_SRC_DEVICE_H__
@@ -12,19 +12,15 @@
namespace Botan {
-/*************************************************
-* Device Based Entropy Source *
-*************************************************/
class BOTAN_DLL Device_EntropySource : public EntropySource
{
public:
std::string name() const { return "RNG Device Reader"; }
+ void poll(Entropy_Accumulator& accum);
+
Device_EntropySource(const std::vector<std::string>& fsnames);
~Device_EntropySource();
-
- u32bit slow_poll(byte[], u32bit);
- u32bit fast_poll(byte[], u32bit);
private:
/**
diff --git a/src/entropy/egd/es_egd.cpp b/src/entropy/egd/es_egd.cpp
index 84773c215..17e366f2b 100644
--- a/src/entropy/egd/es_egd.cpp
+++ b/src/entropy/egd/es_egd.cpp
@@ -1,6 +1,6 @@
-/**
+/*
* EGD EntropySource Source File
-* (C) 1999-2008 Jack Lloyd
+* (C) 1999-2009 Jack Lloyd
*/
#include <botan/es_egd.h>
@@ -8,6 +8,7 @@
#include <botan/parsing.h>
#include <botan/exceptn.h>
#include <cstring>
+#include <stdexcept>
#include <sys/types.h>
#include <sys/stat.h>
@@ -23,28 +24,86 @@
namespace Botan {
-EGD_EntropySource::EGD_Socket::EGD_Socket(const std::string& path)
+EGD_EntropySource::EGD_Socket::EGD_Socket(const std::string& path) :
+ socket_path(path), m_fd(-1)
{
- m_fd = ::socket(PF_LOCAL, SOCK_STREAM, 0);
+ }
- if(m_fd > 0)
+/**
+* Attempt a connection to an EGD/PRNGD socket
+*/
+int EGD_EntropySource::EGD_Socket::open_socket(const std::string& path)
+ {
+ int fd = ::socket(PF_LOCAL, SOCK_STREAM, 0);
+
+ if(fd >= 0)
{
sockaddr_un addr;
std::memset(&addr, 0, sizeof(addr));
addr.sun_family = PF_LOCAL;
if(sizeof(addr.sun_path) < path.length() + 1)
- throw Exception("EGD_EntropySource: Socket path is too long");
+ throw std::invalid_argument("EGD socket path is too long");
+
std::strcpy(addr.sun_path, path.c_str());
int len = sizeof(addr.sun_family) + std::strlen(addr.sun_path) + 1;
- if(::connect(m_fd, reinterpret_cast<struct ::sockaddr*>(&addr), len) < 0)
+ if(::connect(fd, reinterpret_cast<struct ::sockaddr*>(&addr), len) < 0)
{
- ::close(m_fd);
- m_fd = -1;
+ ::close(fd);
+ fd = -1;
}
}
+
+ return fd;
+ }
+
+/**
+* Attempt to read entropy from EGD
+*/
+u32bit EGD_EntropySource::EGD_Socket::read(byte outbuf[], u32bit length)
+ {
+ if(length == 0)
+ return 0;
+
+ if(m_fd < 0)
+ {
+ m_fd = open_socket(socket_path);
+ if(m_fd < 0)
+ return 0;
+ }
+
+ try
+ {
+ // 1 == EGD command for non-blocking read
+ byte egd_read_command[2] = {
+ 1, static_cast<byte>(std::min<u32bit>(length, 255)) };
+
+ if(::write(m_fd, egd_read_command, 2) != 2)
+ throw std::runtime_error("Writing entropy read command to EGD failed");
+
+ byte out_len = 0;
+ if(::read(m_fd, &out_len, 1) != 1)
+ throw std::runtime_error("Reading response length from EGD failed");
+
+ if(out_len > egd_read_command[1])
+ throw std::runtime_error("Bogus length field recieved from EGD");
+
+ ssize_t count = ::read(m_fd, outbuf, out_len);
+
+ if(count != out_len)
+ throw std::runtime_error("Reading entropy result from EGD failed");
+
+ return static_cast<u32bit>(count);
+ }
+ catch(std::exception& e)
+ {
+ this->close();
+ // Will attempt to reopen next poll
+ }
+
+ return 0;
}
void EGD_EntropySource::EGD_Socket::close()
@@ -62,12 +121,7 @@ void EGD_EntropySource::EGD_Socket::close()
EGD_EntropySource::EGD_EntropySource(const std::vector<std::string>& paths)
{
for(size_t i = 0; i != paths.size(); ++i)
- {
- EGD_Socket sock(paths[i]);
-
- if(sock.fd() != -1)
- sockets.push_back(sock);
- }
+ sockets.push_back(EGD_Socket(paths[i]));
}
EGD_EntropySource::~EGD_EntropySource()
@@ -80,46 +134,22 @@ EGD_EntropySource::~EGD_EntropySource()
/**
* Gather Entropy from EGD
*/
-u32bit EGD_EntropySource::slow_poll(byte output[], u32bit length)
+void EGD_EntropySource::poll(Entropy_Accumulator& accum)
{
- if(length > 128)
- length = 128;
+ u32bit go_get = std::min<u32bit>(accum.desired_remaining_bits() / 8, 32);
+
+ MemoryRegion<byte>& io_buffer = accum.get_io_buffer(go_get);
for(size_t i = 0; i != sockets.size(); ++i)
{
- EGD_Socket& socket = sockets[i];
+ u32bit got = sockets[i].read(io_buffer.begin(), io_buffer.size());
- byte buffer[2];
- buffer[0] = 1;
- buffer[1] = static_cast<byte>(length);
-
- if(::write(socket.fd(), buffer, 2) != 2)
- return 0;
-
- byte out_len = 0;
- if(::read(socket.fd(), &out_len, 1) != 1)
- return 0;
-
- if(out_len > length)
- return 0;
-
- ssize_t count = ::read(socket.fd(), output, out_len);
-
- if(count < 0)
- return 0;
-
- return static_cast<u32bit>(count);
+ if(got)
+ {
+ accum.add(io_buffer.begin(), got, 8);
+ break;
+ }
}
-
- return 0;
- }
-
-/**
-* Gather Entropy from EGD, limiting to 64 bytes
-*/
-u32bit EGD_EntropySource::fast_poll(byte output[], u32bit length)
- {
- return slow_poll(output, std::min<u32bit>(length, 64));
}
}
diff --git a/src/entropy/egd/es_egd.h b/src/entropy/egd/es_egd.h
index de80374cc..5fb09fc57 100644
--- a/src/entropy/egd/es_egd.h
+++ b/src/entropy/egd/es_egd.h
@@ -20,8 +20,7 @@ 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);
+ void poll(Entropy_Accumulator& accum);
EGD_EntropySource(const std::vector<std::string>&);
~EGD_EntropySource();
@@ -32,9 +31,12 @@ class BOTAN_DLL EGD_EntropySource : public EntropySource
EGD_Socket(const std::string& path);
void close();
- int fd() const { return m_fd; }
+ u32bit read(byte outbuf[], u32bit length);
private:
- int m_fd;
+ static int open_socket(const std::string& path);
+
+ std::string socket_path;
+ int m_fd; // cached fd
};
std::vector<EGD_Socket> sockets;
diff --git a/src/entropy/entropy_acc.cpp b/src/entropy/entropy_acc.cpp
new file mode 100644
index 000000000..9dc0f1405
--- /dev/null
+++ b/src/entropy/entropy_acc.cpp
@@ -0,0 +1,87 @@
+/**
+* Entropy Accumulator
+* (C) 1999-2009 Jack Lloyd
+*/
+
+#include <botan/entropy_src.h>
+
+namespace Botan {
+
+void Entropy_Accumulator::reset_goal(u32bit entropy_goal)
+ {
+ goal_bits = entropy_goal;
+ collected_bits = 0;
+
+ /*
+ * The buffer is large enough to hold 2*goal_bits of entropy,
+ * or 128 bits, whichever is larger
+ */
+ entropy_buf.create(std::max<u32bit>(goal_bits / 4, 16));
+ io_buffer.destroy();
+ }
+
+MemoryRegion<byte>& Entropy_Accumulator::get_io_buffer(u32bit size)
+ {
+ io_buffer.create(size);
+ return io_buffer;
+ }
+
+u32bit Entropy_Accumulator::desired_remaining_bits() const
+ {
+ if(collected_bits >= goal_bits)
+ return 0;
+ return (goal_bits - collected_bits);
+ }
+
+bool Entropy_Accumulator::polling_goal_achieved() const
+ {
+ return (collected_bits >= goal_bits);
+ }
+
+void Entropy_Accumulator::add(const void* in_void,
+ u32bit length,
+ double entropy_bits_per_byte)
+ {
+ if(length == 0)
+ return;
+
+ entropy_bits_per_byte = std::max(0.0, std::min(entropy_bits_per_byte, 8.0));
+
+ const byte* in = static_cast<const byte*>(in_void);
+
+ u32bit buf_i = 0; // write index into entropy_buf
+ u32bit bytes_collected = 0;
+
+ byte last = 0;
+ byte count = 0;
+
+ for(u32bit i = 0; i != length; ++i)
+ {
+ if(in[i] != last) // run length encode the input
+ {
+ entropy_buf[buf_i] ^= last;
+ buf_i = (buf_i + 1) % entropy_buf.size();
+
+ if(count > 1)
+ {
+ entropy_buf[buf_i] ^= count;
+ buf_i = (buf_i + 1) % entropy_buf.size();
+ }
+
+ ++bytes_collected;
+
+ last = in[i];
+ count = 1;
+ }
+ else
+ ++count;
+ }
+
+ entropy_buf[0] ^= last;
+ entropy_buf[1] ^= count;
+
+ collected_bits += static_cast<u32bit>(entropy_bits_per_byte * bytes_collected);
+ collected_bits = std::min(collected_bits, 8 * entropy_buf.size());
+ }
+
+}
diff --git a/src/entropy/entropy_src.h b/src/entropy/entropy_src.h
index 0891e393f..603bbae15 100644
--- a/src/entropy/entropy_src.h
+++ b/src/entropy/entropy_src.h
@@ -1,26 +1,59 @@
-/*************************************************
-* EntropySource Header File *
-* (C) 2008 Jack Lloyd *
-*************************************************/
+/**
+* EntropySource Header File
+* (C) 2008-2009 Jack Lloyd
+*/
#ifndef BOTAN_ENTROPY_SOURCE_BASE_H__
#define BOTAN_ENTROPY_SOURCE_BASE_H__
-#include <botan/types.h>
+#include <botan/buf_comp.h>
#include <string>
+#include <utility>
namespace Botan {
/**
+* Class used to accumulate the poll results of EntropySources
+*/
+class Entropy_Accumulator
+ {
+ public:
+ Entropy_Accumulator(u32bit entropy_goal)
+ { reset_goal(entropy_goal); }
+
+ const MemoryRegion<byte>& get_entropy_buffer() const
+ { return entropy_buf; }
+
+ MemoryRegion<byte>& get_io_buffer(u32bit size);
+
+ void reset_goal(u32bit entropy_goal);
+
+ u32bit bits_collected() const { return collected_bits; }
+
+ bool polling_goal_achieved() const;
+
+ u32bit desired_remaining_bits() const;
+
+ void add(const void* bytes, u32bit length, double bits_per_byte);
+
+ template<typename T>
+ void add(const T& v, double bits_per_byte)
+ {
+ add(&v, sizeof(T), bits_per_byte);
+ }
+ private:
+ SecureVector<byte> io_buffer, entropy_buf;
+ u32bit collected_bits, goal_bits;
+ };
+
+/**
* Abstract interface to a source of (hopefully unpredictable) system entropy
*/
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 void poll(Entropy_Accumulator& accum) = 0;
virtual ~EntropySource() {}
};
diff --git a/src/entropy/info.txt b/src/entropy/info.txt
index bac1d593f..e0b0320b1 100644
--- a/src/entropy/info.txt
+++ b/src/entropy/info.txt
@@ -4,4 +4,5 @@ load_on auto
<add>
entropy_src.h
+entropy_acc.cpp
</add>
diff --git a/src/entropy/proc_walk/es_ftw.cpp b/src/entropy/proc_walk/es_ftw.cpp
index 1ad6c56b6..406e84cb0 100644
--- a/src/entropy/proc_walk/es_ftw.cpp
+++ b/src/entropy/proc_walk/es_ftw.cpp
@@ -5,7 +5,6 @@
#include <botan/es_ftw.h>
#include <botan/secmem.h>
-#include <botan/xor_buf.h>
#include <cstring>
#include <deque>
@@ -110,49 +109,36 @@ FTW_EntropySource::~FTW_EntropySource()
delete dir;
}
-u32bit FTW_EntropySource::slow_poll(byte buf[], u32bit length)
+void FTW_EntropySource::poll(Entropy_Accumulator& accum)
{
+ const u32bit MAX_FILES_READ_PER_POLL = 1024;
+
if(!dir)
dir = new Directory_Walker(path);
- SecureVector<byte> read_buf(4096);
-
- u32bit bytes_read = 0;
- u32bit buf_i = 0;
+ MemoryRegion<byte>& io_buffer = accum.get_io_buffer(2048);
- while(bytes_read < length * 32)
+ for(u32bit i = 0; i != MAX_FILES_READ_PER_POLL; ++i)
{
int fd = dir->next_fd();
- if(fd == -1) // re-walk
+ // If we've exhaused this walk of the directory, halt the poll
+ if(fd == -1)
{
delete dir;
- dir = new Directory_Walker(path);
- fd = dir->next_fd();
-
- if(fd == -1) // still fails (directory not mounted, etc) -> fail
- return 0;
+ dir = 0;
+ break;
}
- ssize_t got = ::read(fd, read_buf.begin(), read_buf.size());
+ ssize_t got = ::read(fd, io_buffer.begin(), io_buffer.size());
+ ::close(fd);
if(got > 0)
- {
- buf_i = xor_into_buf(buf, buf_i, length, read_buf, got);
-
- // never count any one file for more than 128 bytes
- bytes_read += std::min<u32bit>(got, 128);
- }
+ accum.add(io_buffer.begin(), got, .005);
- ::close(fd);
+ if(accum.polling_goal_achieved())
+ break;
}
-
- return length;
- }
-
-u32bit FTW_EntropySource::fast_poll(byte[], u32bit)
- {
- return 0; // no op
}
}
diff --git a/src/entropy/proc_walk/es_ftw.h b/src/entropy/proc_walk/es_ftw.h
index 5b127943f..a764462c6 100644
--- a/src/entropy/proc_walk/es_ftw.h
+++ b/src/entropy/proc_walk/es_ftw.h
@@ -10,16 +10,15 @@
namespace Botan {
-/*************************************************
-* File Tree Walking Entropy Source *
-*************************************************/
+/**
+* File Tree Walking Entropy Source
+*/
class BOTAN_DLL FTW_EntropySource : public EntropySource
{
public:
std::string name() const { return "Proc Walker"; }
- u32bit slow_poll(byte buf[], u32bit len);
- u32bit fast_poll(byte buf[], u32bit len);
+ void poll(Entropy_Accumulator& accum);
FTW_EntropySource(const std::string& root_dir);
~FTW_EntropySource();
diff --git a/src/entropy/unix_procs/es_unix.cpp b/src/entropy/unix_procs/es_unix.cpp
index 124a08da7..3ac8cd8d3 100644
--- a/src/entropy/unix_procs/es_unix.cpp
+++ b/src/entropy/unix_procs/es_unix.cpp
@@ -1,12 +1,11 @@
-/*************************************************
-* Unix EntropySource Source File *
-* (C) 1999-2008 Jack Lloyd *
-*************************************************/
+/*
+* Unix EntropySource Source File
+* (C) 1999-2009 Jack Lloyd
+*/
#include <botan/es_unix.h>
#include <botan/unix_cmd.h>
#include <botan/parsing.h>
-#include <botan/xor_buf.h>
#include <algorithm>
#include <sys/time.h>
#include <sys/stat.h>
@@ -17,43 +16,40 @@ namespace Botan {
namespace {
-/*************************************************
-* Sort ordering by priority *
-*************************************************/
+/**
+* Sort ordering by priority
+*/
bool Unix_Program_Cmp(const Unix_Program& a, const Unix_Program& b)
{ return (a.priority < b.priority); }
}
-/*************************************************
-* Unix_EntropySource Constructor *
-*************************************************/
+/**
+* Unix_EntropySource Constructor
+*/
Unix_EntropySource::Unix_EntropySource(const std::vector<std::string>& path) :
PATH(path)
{
add_default_sources(sources);
}
-/*************************************************
-* Add sources to the list *
-*************************************************/
+/**
+* Add sources to the list
+*/
void Unix_EntropySource::add_sources(const Unix_Program srcs[], u32bit count)
{
sources.insert(sources.end(), srcs, srcs + count);
std::sort(sources.begin(), sources.end(), Unix_Program_Cmp);
}
-/*************************************************
-* Unix Fast Poll *
-*************************************************/
-u32bit Unix_EntropySource::fast_poll(byte buf[], u32bit length)
+/**
+* Poll for entropy on a generic Unix system, first by grabbing various
+* statistics (stat on common files, getrusage, etc), and then, if more
+* is required, by exec'ing various programs like uname and rpcinfo and
+* reading the output.
+*/
+void Unix_EntropySource::poll(Entropy_Accumulator& accum)
{
- if(length == 0)
- return 0;
- length = std::min<u32bit>(length, 32);
-
- u32bit buf_i = 0;
-
const char* stat_targets[] = {
"/",
"/tmp",
@@ -70,67 +66,50 @@ u32bit Unix_EntropySource::fast_poll(byte buf[], u32bit length)
struct stat statbuf;
clear_mem(&statbuf, 1);
::stat(stat_targets[j], &statbuf);
- buf_i = xor_into_buf(buf, buf_i, length, statbuf);
+ accum.add(&statbuf, sizeof(statbuf), .05);
}
- u32bit ids[] = {
- ::getpid(),
- ::getppid(),
- ::getuid(),
- ::geteuid(),
- ::getegid(),
- ::getpgrp(),
- ::getsid(0)
- };
-
- for(u32bit i = 0; i != sizeof(ids) / sizeof(ids[0]); ++i)
- buf_i = xor_into_buf(buf, buf_i, length, ids[i]);
+ accum.add(::getpid(), 0);
+ accum.add(::getppid(), 0);
+ accum.add(::getuid(), 0);
+ accum.add(::geteuid(), 0);
+ accum.add(::getegid(), 0);
+ accum.add(::getpgrp(), 0);
+ accum.add(::getsid(0), 0);
struct ::rusage usage;
::getrusage(RUSAGE_SELF, &usage);
- buf_i = xor_into_buf(buf, buf_i, length, usage);
+ accum.add(usage, .05);
::getrusage(RUSAGE_CHILDREN, &usage);
- buf_i = xor_into_buf(buf, buf_i, length, usage);
-
- return length;
- }
+ accum.add(usage, .05);
-/*************************************************
-* Unix Slow Poll *
-*************************************************/
-u32bit Unix_EntropySource::slow_poll(byte buf[], u32bit length)
- {
- if(length == 0)
- return 0;
+ if(accum.desired_remaining_bits() < 128)
+ return;
- const u32bit MINIMAL_WORKING = 32;
+ const u32bit MINIMAL_WORKING = 16;
- u32bit total_got = 0;
- u32bit buf_i = 0;
+ MemoryRegion<byte>& io_buffer = accum.get_io_buffer(DEFAULT_BUFFERSIZE);
for(u32bit j = 0; j != sources.size(); j++)
{
DataSource_Command pipe(sources[j].name_and_args, PATH);
- SecureVector<byte> buffer(DEFAULT_BUFFERSIZE);
u32bit got_from_src = 0;
while(!pipe.end_of_data())
{
- u32bit this_loop = pipe.read(buffer, buffer.size());
- buf_i = xor_into_buf(buf, buf_i, length, buffer, this_loop);
- got_from_src += this_loop;
+ u32bit got_this_loop = pipe.read(io_buffer, io_buffer.size());
+ got_from_src += got_this_loop;
+
+ accum.add(io_buffer.begin(), got_this_loop, .005);
}
sources[j].working = (got_from_src >= MINIMAL_WORKING) ? true : false;
- total_got += got_from_src;
- if(total_got >= 128*length)
+ if(accum.polling_goal_achieved())
break;
}
-
- return length;
}
}
diff --git a/src/entropy/unix_procs/es_unix.h b/src/entropy/unix_procs/es_unix.h
index f4af255ca..ba3fd51c2 100644
--- a/src/entropy/unix_procs/es_unix.h
+++ b/src/entropy/unix_procs/es_unix.h
@@ -1,7 +1,7 @@
-/*************************************************
-* Unix EntropySource Header File *
-* (C) 1999-2007 Jack Lloyd *
-*************************************************/
+/*
+* Unix EntropySource Header File
+* (C) 1999-2009 Jack Lloyd
+*/
#ifndef BOTAN_ENTROPY_SRC_UNIX_H__
#define BOTAN_ENTROPY_SRC_UNIX_H__
@@ -12,21 +12,21 @@
namespace Botan {
-/*************************************************
-* Unix Entropy Source *
-*************************************************/
+/**
+* Unix Entropy Source
+*/
class BOTAN_DLL Unix_EntropySource : public EntropySource
{
public:
std::string name() const { return "Unix Entropy Source"; }
+ void poll(Entropy_Accumulator& accum);
+
void add_sources(const Unix_Program[], u32bit);
Unix_EntropySource(const std::vector<std::string>& path);
private:
static void add_default_sources(std::vector<Unix_Program>&);
-
- u32bit fast_poll(byte buf[], u32bit length);
- u32bit slow_poll(byte buf[], u32bit length);
+ void fast_poll(Entropy_Accumulator& accum);
const std::vector<std::string> PATH;
std::vector<Unix_Program> sources;
diff --git a/src/entropy/unix_procs/unix_cmd.cpp b/src/entropy/unix_procs/unix_cmd.cpp
index 4c7f674db..b9558b35c 100644
--- a/src/entropy/unix_procs/unix_cmd.cpp
+++ b/src/entropy/unix_procs/unix_cmd.cpp
@@ -1,7 +1,7 @@
-/*************************************************
-* Unix Command Execution Source File *
-* (C) 1999-2007 Jack Lloyd *
-*************************************************/
+/*
+* Unix Command Execution Source File
+* (C) 1999-2007 Jack Lloyd
+*/
#include <botan/unix_cmd.h>
#include <botan/parsing.h>
@@ -18,9 +18,9 @@ namespace Botan {
namespace {
-/*************************************************
-* Attempt to execute the command *
-************************************************/
+/**
+* Attempt to execute the command
+*/
void do_exec(const std::vector<std::string>& arg_list,
const std::vector<std::string>& paths)
{
@@ -41,9 +41,9 @@ void do_exec(const std::vector<std::string>& arg_list,
}
-/*************************************************
-* Local information about the pipe *
-*************************************************/
+/**
+* Local information about the pipe
+*/
struct pipe_wrapper
{
int fd;
@@ -51,9 +51,9 @@ struct pipe_wrapper
pipe_wrapper() { fd = -1; pid = 0; }
};
-/*************************************************
-* Read from the pipe *
-*************************************************/
+/**
+* Read from the pipe
+*/
u32bit DataSource_Command::read(byte buf[], u32bit length)
{
if(end_of_data())
@@ -83,9 +83,9 @@ u32bit DataSource_Command::read(byte buf[], u32bit length)
return static_cast<u32bit>(got);
}
-/*************************************************
-* Peek at the pipe contents *
-*************************************************/
+/**
+* Peek at the pipe contents
+*/
u32bit DataSource_Command::peek(byte[], u32bit, u32bit) const
{
if(end_of_data())
@@ -93,17 +93,17 @@ u32bit DataSource_Command::peek(byte[], u32bit, u32bit) const
throw Stream_IO_Error("Cannot peek/seek on a command pipe");
}
-/*************************************************
-* Check if we reached EOF *
-*************************************************/
+/**
+* Check if we reached EOF
+*/
bool DataSource_Command::end_of_data() const
{
return (pipe) ? false : true;
}
-/*************************************************
-* Return the Unix file descriptor of the pipe *
-*************************************************/
+/**
+* Return the Unix file descriptor of the pipe
+*/
int DataSource_Command::fd() const
{
if(!pipe)
@@ -111,17 +111,17 @@ int DataSource_Command::fd() const
return pipe->fd;
}
-/*************************************************
-* Return a human-readable ID for this stream *
-*************************************************/
+/**
+* Return a human-readable ID for this stream
+*/
std::string DataSource_Command::id() const
{
return "Unix command: " + arg_list[0];
}
-/*************************************************
-* Create the pipe *
-*************************************************/
+/**
+* Create the pipe
+*/
void DataSource_Command::create_pipe(const std::vector<std::string>& paths)
{
bool found_something = false;
@@ -169,9 +169,9 @@ void DataSource_Command::create_pipe(const std::vector<std::string>& paths)
}
}
-/*************************************************
-* Shutdown the pipe *
-*************************************************/
+/**
+* Shutdown the pipe
+*/
void DataSource_Command::shutdown_pipe()
{
if(pipe)
@@ -204,9 +204,9 @@ void DataSource_Command::shutdown_pipe()
}
}
-/*************************************************
-* DataSource_Command Constructor *
-*************************************************/
+/**
+* DataSource_Command Constructor
+*/
DataSource_Command::DataSource_Command(const std::string& prog_and_args,
const std::vector<std::string>& paths) :
MAX_BLOCK_USECS(100000), KILL_WAIT(10000)
@@ -222,9 +222,9 @@ DataSource_Command::DataSource_Command(const std::string& prog_and_args,
create_pipe(paths);
}
-/*************************************************
-* DataSource_Command Destructor *
-*************************************************/
+/**
+* DataSource_Command Destructor
+*/
DataSource_Command::~DataSource_Command()
{
if(!end_of_data())
diff --git a/src/entropy/unix_procs/unix_cmd.h b/src/entropy/unix_procs/unix_cmd.h
index 8544e7879..66122ea49 100644
--- a/src/entropy/unix_procs/unix_cmd.h
+++ b/src/entropy/unix_procs/unix_cmd.h
@@ -1,7 +1,7 @@
-/*************************************************
-* Unix Command Execution Header File *
-* (C) 1999-2007 Jack Lloyd *
-*************************************************/
+/**
+* Unix Command Execution Header File
+* (C) 1999-2007 Jack Lloyd
+*/
#ifndef BOTAN_UNIX_CMD_H__
#define BOTAN_UNIX_CMD_H__
@@ -13,9 +13,9 @@
namespace Botan {
-/*************************************************
-* Unix Program Info *
-*************************************************/
+/**
+* Unix Program Info
+*/
struct Unix_Program
{
Unix_Program(const char* n, u32bit p)
@@ -26,9 +26,9 @@ struct Unix_Program
bool working;
};
-/*************************************************
-* Command Output DataSource *
-*************************************************/
+/**
+* Command Output DataSource
+*/
class BOTAN_DLL DataSource_Command : public DataSource
{
public:
diff --git a/src/entropy/unix_procs/unix_src.cpp b/src/entropy/unix_procs/unix_src.cpp
index 9d44dbf4f..5e48ba41d 100644
--- a/src/entropy/unix_procs/unix_src.cpp
+++ b/src/entropy/unix_procs/unix_src.cpp
@@ -1,15 +1,15 @@
-/*************************************************
-* Program List for Unix_EntropySource *
-* (C) 1999-2007 Jack Lloyd *
-*************************************************/
+/*
+* Program List for Unix_EntropySource
+* (C) 1999-2007 Jack Lloyd
+*/
#include <botan/es_unix.h>
namespace Botan {
-/*************************************************
-* Default Commands for Entropy Gathering *
-*************************************************/
+/**
+* Default Commands for Entropy Gathering
+*/
void Unix_EntropySource::add_default_sources(std::vector<Unix_Program>& srcs)
{
srcs.push_back(Unix_Program("vmstat", 1));
diff --git a/src/entropy/win32_stats/es_win32.cpp b/src/entropy/win32_stats/es_win32.cpp
index a529ccc1a..0c17f7b02 100644
--- a/src/entropy/win32_stats/es_win32.cpp
+++ b/src/entropy/win32_stats/es_win32.cpp
@@ -1,43 +1,69 @@
/**
* Win32 EntropySource Source File
-* (C) 1999-2008 Jack Lloyd
+* (C) 1999-2009 Jack Lloyd
*/
#include <botan/es_win32.h>
-#include <botan/xor_buf.h>
#include <windows.h>
#include <tlhelp32.h>
namespace Botan {
/**
-* Win32 slow poll using Tooltip32
+* Win32 poll using stats functions including Tooltip32
*/
-u32bit Win32_EntropySource::slow_poll(byte buf[], u32bit length)
+void Win32_EntropySource::poll(Entropy_Accumulator& accum)
{
- if(length == 0)
- return 0;
+ /*
+ First query a bunch of basic statistical stuff, though
+ don't count it for much in terms of contributed entropy.
+ */
+ accum.add(GetTickCount(), 0);
+ accum.add(GetMessagePos(), 0);
+ accum.add(GetMessageTime(), 0);
+ accum.add(GetInputState(), 0);
+ accum.add(GetCurrentProcessId(), 0);
+ accum.add(GetCurrentThreadId() 0);
- const u32bit MAX_ITEMS = length / 4;
+ SYSTEM_INFO sys_info;
+ GetSystemInfo(&sys_info);
+ accum.add(sys_info, 1);
+
+ MEMORYSTATUS mem_info;
+ GlobalMemoryStatus(&mem_info);
+ accum.add(mem_info, 1);
+
+ POINT point;
+ GetCursorPos(&point);
+ accum.add(point, 1);
+
+ GetCaretPos(&point);
+ accum.add(point, 1);
+
+ LARGE_INTEGER perf_counter;
+ QueryPerformanceCounter(&perf_counter);
+ accum.add(perf_count, 0);
- u32bit buf_i = 0;
+ /*
+ Now use the Tooltip library to iterate throug various objects on
+ the system, including processes, threads, and heap objects.
+ */
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
#define TOOLHELP32_ITER(DATA_TYPE, FUNC_FIRST, FUNC_NEXT) \
- { \
- u32bit items = 0; \
- DATA_TYPE info; \
- info.dwSize = sizeof(DATA_TYPE); \
- if(FUNC_FIRST(snapshot, &info)) \
+ if(!accum.polling_goal_achieved()) \
{ \
- do \
+ DATA_TYPE info; \
+ info.dwSize = sizeof(DATA_TYPE); \
+ if(FUNC_FIRST(snapshot, &info)) \
{ \
- if(items++ > MAX_ITEMS) break; \
- buf_i = xor_into_buf(buf, buf_i, length, info); \
- } while(FUNC_NEXT(snapshot, &info)); \
- } \
- }
+ do \
+ { \
+ accum.add(info, 1); \
+ } while(FUNC_NEXT(snapshot, &info)); \
+ } \
+ }
TOOLHELP32_ITER(MODULEENTRY32, Module32First, Module32Next);
TOOLHELP32_ITER(PROCESSENTRY32, Process32First, Process32Next);
@@ -45,85 +71,46 @@ u32bit Win32_EntropySource::slow_poll(byte buf[], u32bit length)
#undef TOOLHELP32_ITER
- u32bit heap_lists_found = 0;
- HEAPLIST32 heap_list;
- heap_list.dwSize = sizeof(HEAPLIST32);
-
- const u32bit HEAP_LISTS_MAX = 32;
- const u32bit HEAP_OBJS_PER_LIST = 128;
- if(Heap32ListFirst(snapshot, &heap_list))
+ if(!accum.polling_goal_achieved())
{
- do
- {
- buf_i = xor_into_buf(buf, buf_i, length, heap_list);
+ u32bit heap_lists_found = 0;
+ HEAPLIST32 heap_list;
+ heap_list.dwSize = sizeof(HEAPLIST32);
- if(heap_lists_found++ > HEAP_LISTS_MAX)
- break;
+ const u32bit HEAP_LISTS_MAX = 32;
+ const u32bit HEAP_OBJS_PER_LIST = 128;
- u32bit heap_objs_found = 0;
- HEAPENTRY32 heap_entry;
- heap_entry.dwSize = sizeof(HEAPENTRY32);
- if(Heap32First(&heap_entry, heap_list.th32ProcessID,
- heap_list.th32HeapID))
+ if(Heap32ListFirst(snapshot, &heap_list))
+ {
+ do
{
- do
+ accum.add(heap_list, 1);
+
+ if(++heap_lists_found > HEAP_LISTS_MAX)
+ break;
+
+ u32bit heap_objs_found = 0;
+ HEAPENTRY32 heap_entry;
+ heap_entry.dwSize = sizeof(HEAPENTRY32);
+ if(Heap32First(&heap_entry, heap_list.th32ProcessID,
+ heap_list.th32HeapID))
{
- if(heap_objs_found++ > HEAP_OBJS_PER_LIST)
- break;
- buf_i = xor_into_buf(buf, buf_i, length, heap_entry);
- } while(Heap32Next(&heap_entry));
- }
- } while(Heap32ListNext(snapshot, &heap_list));
+ do
+ {
+ if(heap_objs_found++ > HEAP_OBJS_PER_LIST)
+ break;
+ accum.add(heap_entry, 1);
+ } while(Heap32Next(&heap_entry));
+ }
+
+ if(accum.polling_goal_achieved())
+ break;
+
+ } while(Heap32ListNext(snapshot, &heap_list));
+ }
}
CloseHandle(snapshot);
-
- return length;
- }
-
-/**
-* Win32 fast poll
-*/
-u32bit Win32_EntropySource::fast_poll(byte buf[], u32bit length)
- {
- if(length == 0)
- return 0;
- length = std::min<u32bit>(length, 32);
-
- u32bit buf_i = 0;
-
- u32bit stats[] = {
- GetTickCount(),
- GetMessagePos(),
- GetMessageTime(),
- GetInputState(),
- GetCurrentProcessId(),
- GetCurrentThreadId()
- };
-
- for(u32bit i = 0; i != sizeof(stats) / sizeof(stats[0]); ++i)
- buf_i = xor_into_buf(buf, buf_i, length, stats[i]);
-
- SYSTEM_INFO sys_info;
- GetSystemInfo(&sys_info);
- buf_i = xor_into_buf(buf, buf_i, length, sys_info);
-
- MEMORYSTATUS mem_info;
- GlobalMemoryStatus(&mem_info);
- buf_i = xor_into_buf(buf, buf_i, length, mem_info);
-
- POINT point;
- GetCursorPos(&point);
- buf_i = xor_into_buf(buf, buf_i, length, point);
-
- GetCaretPos(&point);
- buf_i = xor_into_buf(buf, buf_i, length, point);
-
- LARGE_INTEGER perf_counter;
- QueryPerformanceCounter(&perf_counter);
- buf_i = xor_into_buf(buf, buf_i, length, perf_counter);
-
- return length;
}
}
diff --git a/src/entropy/win32_stats/es_win32.h b/src/entropy/win32_stats/es_win32.h
index 3124bd414..06e3b88cc 100644
--- a/src/entropy/win32_stats/es_win32.h
+++ b/src/entropy/win32_stats/es_win32.h
@@ -1,6 +1,6 @@
/**
* Win32 EntropySource Header File
-* (C) 1999-2008 Jack Lloyd
+* (C) 1999-2009 Jack Lloyd
*/
#ifndef BOTAN_ENTROPY_SRC_WIN32_H__
@@ -17,9 +17,7 @@ class BOTAN_DLL Win32_EntropySource : public EntropySource
{
public:
std::string name() const { return "Win32 Statistics"; }
-
- u32bit fast_poll(byte buf[], u32bit length);
- u32bit slow_poll(byte buf[], u32bit length);
+ void poll(Entropy_Accumulator& accum);
};
}