aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorlloyd <[email protected]>2009-01-31 12:30:31 +0000
committerlloyd <[email protected]>2009-01-31 12:30:31 +0000
commitb118c41af387f765effcca47c08fc2dcc3844778 (patch)
tree5b63b0ee31cdb8226249e3488b065e51ddfc18e3 /src
parent3f5c33c9ece2e7373dde96af045cd5a4853697be (diff)
parentf985e438ca768e59626ff08b143a6c80cf671b9e (diff)
propagate from branch 'net.randombit.botan' (head 4518ef63a5e28e22a61d21a6066d0d4a5cf0616e)
to branch 'net.randombit.botan.entropy-poll-redesign' (head c8e07f10a193b25bab726af99ea2ea77a0f30eaf)
Diffstat (limited to 'src')
-rw-r--r--src/entropy/beos_stats/es_beos.cpp46
-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.cpp55
-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_src.h80
-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
-rw-r--r--src/rng/auto_rng/auto_rng.cpp19
-rw-r--r--src/rng/auto_rng/auto_rng.h4
-rw-r--r--src/rng/hmac_rng/hmac_rng.cpp198
-rw-r--r--src/rng/hmac_rng/hmac_rng.h17
-rw-r--r--src/rng/randpool/randpool.cpp155
-rw-r--r--src/rng/randpool/randpool.h26
-rw-r--r--src/rng/rng.h13
-rw-r--r--src/rng/x931_rng/x931_rng.cpp84
-rw-r--r--src/rng/x931_rng/x931_rng.h17
-rw-r--r--src/timer/timer.cpp16
-rw-r--r--src/timer/timer.h5
-rw-r--r--src/utils/info.txt1
-rw-r--r--src/utils/xor_buf.cpp44
-rw-r--r--src/utils/xor_buf.h18
32 files changed, 674 insertions, 848 deletions
diff --git a/src/entropy/beos_stats/es_beos.cpp b/src/entropy/beos_stats/es_beos.cpp
index b5a5e7fee..02a751e6a 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,52 @@
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);
-
- buf_i = xor_into_buf(buf, buf_i, length, idle_time());
-
- return length;
- }
+ accum.add(info_key, 0);
-/**
-* BeOS slow poll
-*/
-u32bit BeOS_EntropySource::slow_poll(byte buf[], u32bit length)
- {
- if(length == 0)
- return 0;
+ accum.add(idle_time(), 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;
+ if(accum.polling_goal_achieved())
+ break;
+ }
}
}
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..89f981373 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>
@@ -51,12 +51,7 @@ u32bit Device_EntropySource::Device_Reader::get(byte out[], u32bit length,
if(got <= 0)
return 0;
- const u32bit ret = static_cast<u32bit>(got);
-
- if(ret > length)
- return 0;
-
- return ret;
+ return static_cast<u32bit>(got);
}
/**
@@ -79,6 +74,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 +88,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)
{
+ u32bit go_get = std::min<u32bit>(accum.desired_remaining_bits() / 8, 16);
+
+ u32bit read_wait_ms = go_get / 16;
+
+ 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(),
+ read_wait_ms);
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_src.h b/src/entropy/entropy_src.h
index 0891e393f..3fd5c443e 100644
--- a/src/entropy/entropy_src.h
+++ b/src/entropy/entropy_src.h
@@ -1,26 +1,90 @@
-/*************************************************
-* 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 goal) :
+ entropy_goal(goal), collected_bits(0) {}
+
+ virtual ~Entropy_Accumulator() {}
+
+ /**
+ @return cached I/O buffer for repeated polls
+ */
+ MemoryRegion<byte>& get_io_buffer(u32bit size)
+ { io_buffer.create(size); return io_buffer; }
+
+ u32bit bits_collected() const
+ { return static_cast<u32bit>(collected_bits); }
+
+ bool polling_goal_achieved() const
+ { return (collected_bits >= entropy_goal); }
+
+ u32bit desired_remaining_bits() const
+ {
+ if(collected_bits >= entropy_goal)
+ return 0;
+ return (entropy_goal - collected_bits);
+ }
+
+ void add(const void* bytes, u32bit length, double entropy_bits_per_byte)
+ {
+ add_bytes(bytes, length);
+ collected_bits += entropy_bits_per_byte * length;
+ }
+
+ template<typename T>
+ void add(const T& v, double entropy_bits_per_byte)
+ {
+ add(&v, sizeof(T), entropy_bits_per_byte);
+ }
+ private:
+ virtual void add_bytes(const void* bytes, u32bit length) = 0;
+
+ SecureVector<byte> io_buffer;
+ u32bit entropy_goal;
+ double collected_bits;
+ };
+
+class Entropy_Accumulator_BufferedComputation : public Entropy_Accumulator
+ {
+ public:
+ Entropy_Accumulator_BufferedComputation(BufferedComputation& sink,
+ u32bit goal) :
+ Entropy_Accumulator(goal), entropy_sink(sink) {}
+
+ private:
+ virtual void add_bytes(const void* bytes, u32bit length)
+ {
+ entropy_sink.update(reinterpret_cast<const byte*>(bytes), length);
+ }
+
+ BufferedComputation& entropy_sink;
+ };
+
+/**
* 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/proc_walk/es_ftw.cpp b/src/entropy/proc_walk/es_ftw.cpp
index 1ad6c56b6..55f26fa73 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, .01);
- ::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);
};
}
diff --git a/src/rng/auto_rng/auto_rng.cpp b/src/rng/auto_rng/auto_rng.cpp
index 845d958e2..620cc1f61 100644
--- a/src/rng/auto_rng/auto_rng.cpp
+++ b/src/rng/auto_rng/auto_rng.cpp
@@ -76,19 +76,15 @@ namespace {
*/
void add_entropy_sources(RandomNumberGenerator* rng)
{
+
+ // Add a high resolution timer, if available
#if defined(BOTAN_HAS_TIMER_HARDWARE)
rng->add_entropy_source(new Hardware_Timer);
-#endif
-
-#if defined(BOTAN_HAS_TIMER_POSIX)
+#elif defined(BOTAN_HAS_TIMER_POSIX)
rng->add_entropy_source(new POSIX_Timer);
-#endif
-
-#if defined(BOTAN_HAS_TIMER_UNIX)
+#elif defined(BOTAN_HAS_TIMER_UNIX)
rng->add_entropy_source(new Unix_Timer);
-#endif
-
-#if defined(BOTAN_HAS_TIMER_WIN32)
+#elif defined(BOTAN_HAS_TIMER_WIN32)
rng->add_entropy_source(new Win32_Timer);
#endif
@@ -114,7 +110,6 @@ void add_entropy_sources(RandomNumberGenerator* rng)
rng->add_entropy_source(new FTW_EntropySource("/proc"));
#endif
-
#if defined(BOTAN_HAS_ENTROPY_SRC_WIN32)
rng->add_entropy_source(new Win32_EntropySource);
#endif
@@ -132,7 +127,7 @@ void add_entropy_sources(RandomNumberGenerator* rng)
}
-AutoSeeded_RNG::AutoSeeded_RNG()
+AutoSeeded_RNG::AutoSeeded_RNG(u32bit poll_bits)
{
rng = 0;
@@ -152,7 +147,7 @@ AutoSeeded_RNG::AutoSeeded_RNG()
add_entropy_sources(rng);
- rng->reseed();
+ rng->reseed(poll_bits);
}
}
diff --git a/src/rng/auto_rng/auto_rng.h b/src/rng/auto_rng/auto_rng.h
index dea735470..5536f2b8e 100644
--- a/src/rng/auto_rng/auto_rng.h
+++ b/src/rng/auto_rng/auto_rng.h
@@ -25,13 +25,13 @@ class BOTAN_DLL AutoSeeded_RNG : public RandomNumberGenerator
std::string name() const
{ return "AutoSeeded(" + rng->name() + ")"; }
- void reseed() { rng->reseed(); }
+ void reseed(u32bit poll_bits) { rng->reseed(poll_bits); }
void add_entropy_source(EntropySource* es)
{ rng->add_entropy_source(es); }
void add_entropy(const byte in[], u32bit len)
{ rng->add_entropy(in, len); }
- AutoSeeded_RNG();
+ AutoSeeded_RNG(u32bit poll_bits = 256);
~AutoSeeded_RNG() { delete rng; }
private:
RandomNumberGenerator* rng;
diff --git a/src/rng/hmac_rng/hmac_rng.cpp b/src/rng/hmac_rng/hmac_rng.cpp
index 188c32689..458118e11 100644
--- a/src/rng/hmac_rng/hmac_rng.cpp
+++ b/src/rng/hmac_rng/hmac_rng.cpp
@@ -1,7 +1,7 @@
-/*************************************************
-* HMAC_RNG Source File *
-* (C) 2008 Jack Lloyd *
-*************************************************/
+/*
+* HMAC_RNG
+* (C) 2008-2009 Jack Lloyd
+*/
#include <botan/hmac_rng.h>
#include <botan/loadstor.h>
@@ -16,9 +16,9 @@ namespace Botan {
namespace {
void hmac_prf(MessageAuthenticationCode* prf,
- MemoryRegion<byte>& K,
- u32bit& counter,
- const std::string& label)
+ MemoryRegion<byte>& K,
+ u32bit& counter,
+ const std::string& label)
{
prf->update(K, K.size());
prf->update(label);
@@ -31,24 +31,13 @@ void hmac_prf(MessageAuthenticationCode* prf,
}
-/*************************************************
-* Generate a buffer of random bytes *
-*************************************************/
+/**
+* Generate a buffer of random bytes
+*/
void HMAC_RNG::randomize(byte out[], u32bit length)
{
- /* Attempt to seed if we are currently not seeded, or if the
- counter is greater than 2^20
-
- If HMAC_RNG is wrapped in an X9.31/AES PRNG (the default), this
- means a reseed will be kicked off every 16 MiB of RNG output.
- */
- if(!is_seeded() || counter >= 0x100000)
- {
- reseed();
-
- if(!is_seeded())
- throw PRNG_Unseeded(name() + " seeding attempt failed");
- }
+ if(!is_seeded())
+ throw PRNG_Unseeded(name());
/*
HMAC KDF as described in E-t-E, using a CTXinfo of "rng"
@@ -63,94 +52,43 @@ void HMAC_RNG::randomize(byte out[], u32bit length)
out += copied;
length -= copied;
}
-
- /* Every once in a while do a fast poll of a entropy source */
- if(entropy_sources.size() && (counter % 65536 == 0))
- {
- u32bit got = entropy_sources.at(source_index)->
- fast_poll(io_buffer, io_buffer.size());
-
- source_index = (source_index + 1) % entropy_sources.size();
- extractor->update(io_buffer, got);
- io_buffer.clear();
- }
}
/**
* Reseed the internal state, also accepting user input to include
*/
-void HMAC_RNG::reseed_with_input(const byte input[], u32bit input_length)
+void HMAC_RNG::reseed_with_input(u32bit poll_bits,
+ const byte input[], u32bit input_length)
{
- if(entropy_sources.size())
+ /**
+ Using the terminology of E-t-E, XTR is the MAC function (normally
+ HMAC) seeded with XTS (below) and we form SKM, the key material, by
+ fast polling each source, and then slow polling as many as we think
+ we need (in the following loop), and feeding all of the poll
+ results, along with any optional user input, along with, finally,
+ feedback of the current PRK value, into the extractor function.
+ */
+
+ Entropy_Accumulator_BufferedComputation accum(*extractor, poll_bits);
+
+ for(u32bit i = 0; i < entropy_sources.size(); ++i)
{
- /**
- Using the terminology of E-t-E, XTR is the MAC function (normally
- HMAC) seeded with XTS (below) and we form SKM, the key material, by
- fast polling each source, and then slow polling as many as we think
- we need (in the following loop), and feeding all of the poll
- results, along with any optional user input, along with, finally,
- feedback of the current PRK value, into the extractor function.
- */
-
- /*
- Previously this function did entropy estimation. However the paper
-
- "Boaz Barak, Shai Halevi: A model and architecture for
- pseudo-random generation with applications to /dev/random. ACM
- Conference on Computer and Communications Security 2005."
-
- provides a pretty strong case to not even try, since what we are
- really interested in is the *conditional* entropy from the point
- of view of an unknown attacker, which is impossible to
- calculate. They recommend, if an entropy estimate of some kind
- is needed, to use a low static estimate instead. We use here an
- estimate of 1 bit per byte.
-
- One thing I had been concerned about initially was that people
- without any randomness source enabled (much more likely in the
- days when you had to enable them manually) would find the RNG
- was unseeded and then pull the manuever some OpenSSL users did
- and seed the RNG with a constant string. However, upon further
- thought, I've decided that people who do that deserve to lose
- anyway.
- */
-
- for(u32bit j = 0; j < entropy_sources.size(); ++j)
- {
- const u32bit got =
- entropy_sources[j]->fast_poll(io_buffer, io_buffer.size());
-
- entropy += got;
- extractor->update(io_buffer, got);
- io_buffer.clear();
- }
-
- for(u32bit j = 0; j != entropy_sources.size(); ++j)
- {
- const u32bit got =
- entropy_sources[j]->slow_poll(io_buffer, io_buffer.size());
-
- entropy += got;
- extractor->update(io_buffer, got);
- io_buffer.clear();
- }
+ if(accum.polling_goal_achieved())
+ break;
+
+ entropy_sources[i]->poll(accum);
}
- /*
- And now add the user-provided input, if any
- */
+ // And now add the user-provided input, if any
if(input_length)
- {
- extractor->update(input, input_length);
- entropy += input_length;
- }
+ accum.add(input, input_length, 1);
/*
- It is necessary to feed forward poll data. Otherwise, a good
- poll (collecting a large amount of conditional entropy) followed
- by a bad one (collecting little) would be unsafe. Do this by
- generating new PRF outputs using the previous key and feeding them
- into the extractor function.
+ It is necessary to feed forward poll data. Otherwise, a good poll
+ (collecting a large amount of conditional entropy) followed by a
+ bad one (collecting little) would be unsafe. Do this by generating
+ new PRF outputs using the previous key and feeding them into the
+ extractor function.
Cycle the RNG once (CTXinfo="rng"), then generate a new PRF output
using the CTXinfo "reseed". Provide these values as input to the
@@ -174,77 +112,66 @@ void HMAC_RNG::reseed_with_input(const byte input[], u32bit input_length)
K.clear();
counter = 0;
- // Upper bound entropy estimate at the extractor output size
- entropy = std::min<u32bit>(entropy, 8 * extractor->OUTPUT_LENGTH);
+ if(input_length || accum.bits_collected() >= poll_bits)
+ seeded = true;
}
/**
* Reseed the internal state
*/
-void HMAC_RNG::reseed()
+void HMAC_RNG::reseed(u32bit poll_bits)
{
- reseed_with_input(0, 0);
+ reseed_with_input(poll_bits, 0, 0);
}
/**
-Add user-supplied entropy by reseeding and including this
-input among the poll data
+* Add user-supplied entropy by reseeding and including this
+* input among the poll data
*/
void HMAC_RNG::add_entropy(const byte input[], u32bit length)
{
- reseed_with_input(input, length);
+ reseed_with_input(0, input, length);
}
-/*************************************************
-* Add another entropy source to the list *
-*************************************************/
+/**
+* Add another entropy source to the list
+*/
void HMAC_RNG::add_entropy_source(EntropySource* src)
{
entropy_sources.push_back(src);
}
-/*************************************************
-* Check if the the pool is seeded *
-*************************************************/
-bool HMAC_RNG::is_seeded() const
- {
- return (entropy >= 8 * prf->OUTPUT_LENGTH);
- }
-
- /*************************************************
-* Clear memory of sensitive data *
-*************************************************/
+/*
+* Clear memory of sensitive data
+*/
void HMAC_RNG::clear() throw()
{
extractor->clear();
prf->clear();
K.clear();
- entropy = 0;
counter = 0;
- source_index = 0;
+ seeded = false;
}
-/*************************************************
-* Return the name of this type *
-*************************************************/
+/**
+* Return the name of this type
+*/
std::string HMAC_RNG::name() const
{
return "HMAC_RNG(" + extractor->name() + "," + prf->name() + ")";
}
-/*************************************************
-* HMAC_RNG Constructor *
-*************************************************/
+/**
+* HMAC_RNG Constructor
+*/
HMAC_RNG::HMAC_RNG(MessageAuthenticationCode* extractor_mac,
MessageAuthenticationCode* prf_mac) :
- extractor(extractor_mac), prf(prf_mac), io_buffer(96)
+ extractor(extractor_mac), prf(prf_mac)
{
- entropy = 0;
-
// First PRF inputs are all zero, as specified in section 2
K.create(prf->OUTPUT_LENGTH);
counter = 0;
- source_index = 0;
+ seeded = false;
/*
Normally we want to feedback PRF output into the input to the
@@ -275,9 +202,9 @@ HMAC_RNG::HMAC_RNG(MessageAuthenticationCode* extractor_mac,
xts.length());
}
-/*************************************************
-* HMAC_RNG Destructor *
-*************************************************/
+/**
+* HMAC_RNG Destructor
+*/
HMAC_RNG::~HMAC_RNG()
{
delete extractor;
@@ -286,7 +213,6 @@ HMAC_RNG::~HMAC_RNG()
std::for_each(entropy_sources.begin(), entropy_sources.end(),
del_fun<EntropySource>());
- entropy = 0;
counter = 0;
}
diff --git a/src/rng/hmac_rng/hmac_rng.h b/src/rng/hmac_rng/hmac_rng.h
index b9ea064c3..16adddd60 100644
--- a/src/rng/hmac_rng/hmac_rng.h
+++ b/src/rng/hmac_rng/hmac_rng.h
@@ -1,7 +1,7 @@
-/*************************************************
-* HMAC RNG *
-* (C) 2008 Jack Lloyd *
-*************************************************/
+/*
+* HMAC RNG
+* (C) 2008 Jack Lloyd
+*/
#ifndef BOTAN_HMAC_RNG_H__
#define BOTAN_HMAC_RNG_H__
@@ -26,11 +26,11 @@ class BOTAN_DLL HMAC_RNG : public RandomNumberGenerator
{
public:
void randomize(byte buf[], u32bit len);
- bool is_seeded() const;
+ bool is_seeded() const { return seeded; }
void clear() throw();
std::string name() const;
- void reseed();
+ void reseed(u32bit poll_bits);
void add_entropy_source(EntropySource* es);
void add_entropy(const byte[], u32bit);
@@ -39,13 +39,14 @@ class BOTAN_DLL HMAC_RNG : public RandomNumberGenerator
~HMAC_RNG();
private:
- void reseed_with_input(const byte input[], u32bit length);
+ void reseed_with_input(u32bit poll_bits,
+ const byte input[], u32bit length);
MessageAuthenticationCode* extractor;
MessageAuthenticationCode* prf;
std::vector<EntropySource*> entropy_sources;
- u32bit entropy;
+ bool seeded;
SecureVector<byte> K, io_buffer;
u32bit counter, source_index;
diff --git a/src/rng/randpool/randpool.cpp b/src/rng/randpool/randpool.cpp
index e35ee22ca..af36c335f 100644
--- a/src/rng/randpool/randpool.cpp
+++ b/src/rng/randpool/randpool.cpp
@@ -1,7 +1,7 @@
-/*************************************************
-* Randpool Source File *
-* (C) 1999-2008 Jack Lloyd *
-*************************************************/
+/*
+* Randpool Source File
+* (C) 1999-2009 Jack Lloyd
+*/
#include <botan/randpool.h>
#include <botan/loadstor.h>
@@ -14,9 +14,9 @@ namespace Botan {
namespace {
-/*************************************************
-* PRF based on a MAC *
-*************************************************/
+/**
+* PRF based on a MAC
+*/
enum RANDPOOL_PRF_TAG {
CIPHER_KEY = 0,
MAC_KEY = 1,
@@ -25,18 +25,13 @@ enum RANDPOOL_PRF_TAG {
}
-/*************************************************
-* Generate a buffer of random bytes *
-*************************************************/
+/**
+* Generate a buffer of random bytes
+*/
void Randpool::randomize(byte out[], u32bit length)
{
if(!is_seeded())
- {
- reseed();
-
- if(!is_seeded())
- throw PRNG_Unseeded(name());
- }
+ throw PRNG_Unseeded(name());
update_buffer();
while(length)
@@ -49,15 +44,15 @@ void Randpool::randomize(byte out[], u32bit length)
}
}
-/*************************************************
-* Refill the output buffer *
-*************************************************/
+/**
+* Refill the output buffer
+*/
void Randpool::update_buffer()
{
const u64bit timestamp = system_time();
- for(u32bit j = 0; j != counter.size(); ++j)
- if(++counter[j])
+ for(u32bit i = 0; i != counter.size(); ++i)
+ if(++counter[i])
break;
store_be(timestamp, counter + 4);
@@ -65,17 +60,17 @@ void Randpool::update_buffer()
mac->update(counter, counter.size());
SecureVector<byte> mac_val = mac->final();
- for(u32bit j = 0; j != mac_val.size(); ++j)
- buffer[j % buffer.size()] ^= mac_val[j];
+ for(u32bit i = 0; i != mac_val.size(); ++i)
+ buffer[i % buffer.size()] ^= mac_val[i];
cipher->encrypt(buffer);
if(counter[0] % ITERATIONS_BEFORE_RESEED == 0)
mix_pool();
}
-/*************************************************
-* Mix the entropy pool *
-*************************************************/
+/**
+* Mix the entropy pool
+*/
void Randpool::mix_pool()
{
const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE;
@@ -90,10 +85,10 @@ void Randpool::mix_pool()
xor_buf(pool, buffer, BLOCK_SIZE);
cipher->encrypt(pool);
- for(u32bit j = 1; j != POOL_BLOCKS; ++j)
+ for(u32bit i = 1; i != POOL_BLOCKS; ++i)
{
- const byte* previous_block = pool + BLOCK_SIZE*(j-1);
- byte* this_block = pool + BLOCK_SIZE*j;
+ const byte* previous_block = pool + BLOCK_SIZE*(i-1);
+ byte* this_block = pool + BLOCK_SIZE*i;
xor_buf(this_block, previous_block, BLOCK_SIZE);
cipher->encrypt(this_block);
}
@@ -101,48 +96,19 @@ void Randpool::mix_pool()
update_buffer();
}
-/*************************************************
-* Reseed the internal state *
-*************************************************/
-void Randpool::reseed()
+/**
+* Reseed the internal state
+*/
+void Randpool::reseed(u32bit poll_bits)
{
- SecureVector<byte> buffer(128);
-
- u32bit entropy_est = 0;
+ Entropy_Accumulator_BufferedComputation accum(*mac, poll_bits);
- /*
- When we reseed, assume we get 1 bit per byte sampled.
-
- This class used to perform entropy estimation, but what we really
- want to measure is the conditional entropy of the data with respect
- to an unknown attacker with unknown capabilities. For this reason
- making any sort of sane estimate is impossible. See also
- "Boaz Barak, Shai Halevi: A model and architecture for
- pseudo-random generation with applications to /dev/random. ACM
- Conference on Computer and Communications Security 2005."
- */
-
- // First do a fast poll of all sources (no matter what)
- for(u32bit j = 0; j != entropy_sources.size(); ++j)
+ for(u32bit i = 0; i != entropy_sources.size(); ++i)
{
- u32bit got = entropy_sources[j]->fast_poll(buffer, buffer.size());
-
- mac->update(buffer, got);
- entropy_est += got;
- buffer.clear();
- }
+ entropy_sources[i]->poll(accum);
- // 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());
-
- mac->update(buffer, got);
- entropy_est += got;
-
- if(entropy_est > 512)
+ if(accum.polling_goal_achieved())
break;
- buffer.clear();
}
SecureVector<byte> mac_val = mac->final();
@@ -150,41 +116,34 @@ void Randpool::reseed()
xor_buf(pool, mac_val, mac_val.size());
mix_pool();
- entropy = std::min<u32bit>(entropy + entropy_est, 8 * mac_val.size());
+ if(accum.bits_collected() >= poll_bits)
+ seeded = true;
}
-/*************************************************
-* Add user-supplied entropy *
-*************************************************/
+/**
+* Add user-supplied entropy
+*/
void Randpool::add_entropy(const byte input[], u32bit length)
{
SecureVector<byte> mac_val = mac->process(input, length);
xor_buf(pool, mac_val, mac_val.size());
mix_pool();
- // Assume 1 bit conditional entropy per byte of input
- entropy = std::min<u32bit>(entropy + length, 8 * mac_val.size());
+ if(length)
+ seeded = true;
}
-/*************************************************
-* Add another entropy source to the list *
-*************************************************/
+/**
+* Add another entropy source to the list
+*/
void Randpool::add_entropy_source(EntropySource* src)
{
entropy_sources.push_back(src);
}
-/*************************************************
-* Check if the the pool is seeded *
-*************************************************/
-bool Randpool::is_seeded() const
- {
- return (entropy >= 7 * mac->OUTPUT_LENGTH);
- }
-
-/*************************************************
-* Clear memory of sensitive data *
-*************************************************/
+/**
+* Clear memory of sensitive data
+*/
void Randpool::clear() throw()
{
cipher->clear();
@@ -192,20 +151,20 @@ void Randpool::clear() throw()
pool.clear();
buffer.clear();
counter.clear();
- entropy = 0;
+ seeded = false;
}
-/*************************************************
-* Return the name of this type *
-*************************************************/
+/**
+* Return the name of this type
+*/
std::string Randpool::name() const
{
return "Randpool(" + cipher->name() + "," + mac->name() + ")";
}
-/*************************************************
-* Randpool Constructor *
-*************************************************/
+/**
+* Randpool Constructor
+*/
Randpool::Randpool(BlockCipher* cipher_in,
MessageAuthenticationCode* mac_in,
u32bit pool_blocks,
@@ -231,12 +190,12 @@ Randpool::Randpool(BlockCipher* cipher_in,
buffer.create(BLOCK_SIZE);
pool.create(POOL_BLOCKS * BLOCK_SIZE);
counter.create(12);
- entropy = 0;
+ seeded = false;
}
-/*************************************************
-* Randpool Destructor *
-*************************************************/
+/**
+* Randpool Destructor
+*/
Randpool::~Randpool()
{
delete cipher;
@@ -244,8 +203,6 @@ Randpool::~Randpool()
std::for_each(entropy_sources.begin(), entropy_sources.end(),
del_fun<EntropySource>());
-
- entropy = 0;
}
}
diff --git a/src/rng/randpool/randpool.h b/src/rng/randpool/randpool.h
index f6bae9d52..f44527609 100644
--- a/src/rng/randpool/randpool.h
+++ b/src/rng/randpool/randpool.h
@@ -1,7 +1,7 @@
-/*************************************************
-* Randpool Header File *
-* (C) 1999-2008 Jack Lloyd *
-*************************************************/
+/*
+* Randpool Header File
+* (C) 1999-2008 Jack Lloyd
+*/
#ifndef BOTAN_RANDPOOL_H__
#define BOTAN_RANDPOOL_H__
@@ -13,22 +13,22 @@
namespace Botan {
-/*************************************************
-* Randpool *
-*************************************************/
+/**
+* Randpool
+*/
class BOTAN_DLL Randpool : public RandomNumberGenerator
{
public:
void randomize(byte[], u32bit);
- bool is_seeded() const;
+ bool is_seeded() const { return seeded; }
void clear() throw();
std::string name() const;
- void reseed();
- void add_entropy_source(EntropySource*);
- void add_entropy(const byte[], u32bit);
+ void reseed(u32bit bits_to_collect);
+ void add_entropy_source(EntropySource* es);
+ void add_entropy(const byte input[], u32bit length);
- Randpool(BlockCipher*, MessageAuthenticationCode*,
+ Randpool(BlockCipher* cipher, MessageAuthenticationCode* mac,
u32bit pool_blocks = 32,
u32bit iterations_before_reseed = 128);
@@ -43,7 +43,7 @@ class BOTAN_DLL Randpool : public RandomNumberGenerator
std::vector<EntropySource*> entropy_sources;
SecureVector<byte> pool, buffer, counter;
- u32bit entropy;
+ bool seeded;
};
}
diff --git a/src/rng/rng.h b/src/rng/rng.h
index fb92bb3c5..7fc6ee439 100644
--- a/src/rng/rng.h
+++ b/src/rng/rng.h
@@ -1,7 +1,7 @@
-/*************************************************
-* RandomNumberGenerator Header File *
-* (C) 1999-2008 Jack Lloyd *
-*************************************************/
+/*
+* RandomNumberGenerator Header File
+* (C) 1999-2009 Jack Lloyd
+*/
#ifndef BOTAN_RANDOM_NUMBER_GENERATOR_H__
#define BOTAN_RANDOM_NUMBER_GENERATOR_H__
@@ -54,8 +54,10 @@ class BOTAN_DLL RandomNumberGenerator
/**
* Seed this RNG using the entropy sources it contains.
+ * @param bits_to_collect is the number of bits of entropy to
+ attempt to gather from the entropy sources
*/
- virtual void reseed() {}
+ virtual void reseed(u32bit bits_to_collect) = 0;
/**
* Add this entropy source to the RNG object
@@ -88,6 +90,7 @@ class BOTAN_DLL Null_RNG : public RandomNumberGenerator
void clear() throw() {}
std::string name() const { return "Null_RNG"; }
+ void reseed(u32bit) {}
bool is_seeded() const { return false; }
void add_entropy(const byte[], u32bit) {}
void add_entropy_source(EntropySource* es) { delete es; }
diff --git a/src/rng/x931_rng/x931_rng.cpp b/src/rng/x931_rng/x931_rng.cpp
index 619c37e57..e77f04ae4 100644
--- a/src/rng/x931_rng/x931_rng.cpp
+++ b/src/rng/x931_rng/x931_rng.cpp
@@ -1,7 +1,7 @@
-/*************************************************
-* ANSI X9.31 RNG Source File *
-* (C) 1999-2008 Jack Lloyd *
-*************************************************/
+/*
+* ANSI X9.31 RNG Source File
+* (C) 1999-2009 Jack Lloyd
+*/
#include <botan/x931_rng.h>
#include <botan/xor_buf.h>
@@ -9,13 +9,13 @@
namespace Botan {
-/*************************************************
-* Generate a buffer of random bytes *
-*************************************************/
+/**
+* Generate a buffer of random bytes
+*/
void ANSI_X931_RNG::randomize(byte out[], u32bit length)
{
if(!is_seeded())
- reseed();
+ throw PRNG_Unseeded(name());
while(length)
{
@@ -31,9 +31,9 @@ void ANSI_X931_RNG::randomize(byte out[], u32bit length)
}
}
-/*************************************************
-* Refill the internal state *
-*************************************************/
+/**
+* Refill the internal state
+*/
void ANSI_X931_RNG::update_buffer()
{
SecureVector<byte> DT(cipher->BLOCK_SIZE);
@@ -50,13 +50,11 @@ void ANSI_X931_RNG::update_buffer()
position = 0;
}
-/*************************************************
-* Reseed the internal state *
-*************************************************/
-void ANSI_X931_RNG::reseed()
+/**
+* Reset V and the cipher key with new values
+*/
+void ANSI_X931_RNG::rekey()
{
- prng->reseed();
-
if(prng->is_seeded())
{
SecureVector<byte> key(cipher->MAXIMUM_KEYLENGTH);
@@ -71,33 +69,43 @@ void ANSI_X931_RNG::reseed()
}
}
-/*************************************************
-* Add a entropy source to the underlying PRNG *
-*************************************************/
+/**
+* Reseed the internal state
+*/
+void ANSI_X931_RNG::reseed(u32bit poll_bits)
+ {
+ prng->reseed(poll_bits);
+ rekey();
+ }
+
+/**
+* Add a entropy source to the underlying PRNG
+*/
void ANSI_X931_RNG::add_entropy_source(EntropySource* src)
{
prng->add_entropy_source(src);
}
-/*************************************************
-* Add some entropy to the underlying PRNG *
-*************************************************/
+/**
+* Add some entropy to the underlying PRNG
+*/
void ANSI_X931_RNG::add_entropy(const byte input[], u32bit length)
{
prng->add_entropy(input, length);
+ rekey();
}
-/*************************************************
-* Check if the the PRNG is seeded *
-*************************************************/
+/**
+* Check if the the PRNG is seeded
+*/
bool ANSI_X931_RNG::is_seeded() const
{
return V.has_items();
}
-/*************************************************
-* Clear memory of sensitive data *
-*************************************************/
+/**
+* Clear memory of sensitive data
+*/
void ANSI_X931_RNG::clear() throw()
{
cipher->clear();
@@ -108,17 +116,17 @@ void ANSI_X931_RNG::clear() throw()
position = 0;
}
-/*************************************************
-* Return the name of this type *
-*************************************************/
+/**
+* Return the name of this type
+*/
std::string ANSI_X931_RNG::name() const
{
return "X9.31(" + cipher->name() + ")";
}
-/*************************************************
-* ANSI X931 RNG Constructor *
-*************************************************/
+/**
+* ANSI X931 RNG Constructor
+*/
ANSI_X931_RNG::ANSI_X931_RNG(BlockCipher* cipher_in,
RandomNumberGenerator* prng_in)
{
@@ -132,9 +140,9 @@ ANSI_X931_RNG::ANSI_X931_RNG(BlockCipher* cipher_in,
position = 0;
}
-/*************************************************
-* ANSI X931 RNG Destructor *
-*************************************************/
+/**
+* ANSI X931 RNG Destructor
+*/
ANSI_X931_RNG::~ANSI_X931_RNG()
{
delete cipher;
diff --git a/src/rng/x931_rng/x931_rng.h b/src/rng/x931_rng/x931_rng.h
index e1d090c3c..b1cef8df3 100644
--- a/src/rng/x931_rng/x931_rng.h
+++ b/src/rng/x931_rng/x931_rng.h
@@ -1,7 +1,7 @@
-/*************************************************
-* ANSI X9.31 RNG Header File *
-* (C) 1999-2008 Jack Lloyd *
-*************************************************/
+/*
+* ANSI X9.31 RNG Header File
+* (C) 1999-2009 Jack Lloyd
+*/
#ifndef BOTAN_ANSI_X931_RNG_H__
#define BOTAN_ANSI_X931_RNG_H__
@@ -11,9 +11,9 @@
namespace Botan {
-/*************************************************
-* ANSI X9.31 RNG *
-*************************************************/
+/**
+* ANSI X9.31 RNG
+*/
class BOTAN_DLL ANSI_X931_RNG : public RandomNumberGenerator
{
public:
@@ -22,13 +22,14 @@ class BOTAN_DLL ANSI_X931_RNG : public RandomNumberGenerator
void clear() throw();
std::string name() const;
- void reseed();
+ void reseed(u32bit poll_bits);
void add_entropy_source(EntropySource*);
void add_entropy(const byte[], u32bit);
ANSI_X931_RNG(BlockCipher*, RandomNumberGenerator*);
~ANSI_X931_RNG();
private:
+ void rekey();
void update_buffer();
BlockCipher* cipher;
diff --git a/src/timer/timer.cpp b/src/timer/timer.cpp
index 8758aad21..a801761cf 100644
--- a/src/timer/timer.cpp
+++ b/src/timer/timer.cpp
@@ -1,6 +1,6 @@
/**
* Timestamp Functions Source File
-* (C) 1999-2008 Jack Lloyd
+* (C) 1999-2009 Jack Lloyd
*/
#include <botan/timer.h>
@@ -21,19 +21,10 @@ u64bit system_time()
/**
* Read the clock and return the output
*/
-u32bit Timer::fast_poll(byte out[], u32bit length)
+void Timer::poll(Entropy_Accumulator& accum)
{
const u64bit clock_value = this->clock();
-
- for(u32bit j = 0; j != sizeof(clock_value); ++j)
- out[j % length] ^= get_byte(j, clock_value);
-
- return (length < 8) ? length : 8;
- }
-
-u32bit Timer::slow_poll(byte out[], u32bit length)
- {
- return fast_poll(out, length);
+ accum.add(clock_value, 0);
}
/**
@@ -56,5 +47,4 @@ u64bit ANSI_Clock_Timer::clock() const
return combine_timers(std::time(0), std::clock(), CLOCKS_PER_SEC);
}
-
}
diff --git a/src/timer/timer.h b/src/timer/timer.h
index af2c58dcb..0e0dcc62e 100644
--- a/src/timer/timer.h
+++ b/src/timer/timer.h
@@ -1,6 +1,6 @@
/**
* Timestamp Functions Header File
-* (C) 1999-2008 Jack Lloyd
+* (C) 1999-2009 Jack Lloyd
*/
#ifndef BOTAN_TIMERS_H__
@@ -21,8 +21,7 @@ class BOTAN_DLL Timer : public EntropySource
*/
virtual u64bit clock() const = 0;
- u32bit slow_poll(byte[], u32bit);
- u32bit fast_poll(byte[], u32bit);
+ void poll(Entropy_Accumulator& accum);
virtual ~Timer() {}
protected:
diff --git a/src/utils/info.txt b/src/utils/info.txt
index 915ce50b0..ffc19c852 100644
--- a/src/utils/info.txt
+++ b/src/utils/info.txt
@@ -42,6 +42,5 @@ util.cpp
util.h
version.cpp
version.h
-xor_buf.cpp
xor_buf.h
</add>
diff --git a/src/utils/xor_buf.cpp b/src/utils/xor_buf.cpp
deleted file mode 100644
index 779be81c3..000000000
--- a/src/utils/xor_buf.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
-* XOR operations
-* (C) 1999-2008 Jack Lloyd
-*/
-
-#include <botan/xor_buf.h>
-#include <botan/loadstor.h>
-
-namespace Botan {
-
-/**
-* Xor values into buffer
-*/
-u32bit xor_into_buf(byte buf[], u32bit buf_i, u32bit length,
- const void* in_void, u32bit in_len)
- {
- const byte* in = static_cast<const byte*>(in_void);
-
- byte last = 0;
- byte count = 0;
-
- for(u32bit i = 0; i != in_len; ++i)
- {
- if(in[i] != last)
- {
- buf[buf_i] ^= last;
- buf_i = (buf_i + 1) % length;
-
- buf[buf_i] ^= count;
- buf_i = (buf_i + 1) % length;
-
- last = in[i];
- count = 1;
- }
- else
- ++count;
- }
-
- // final values of last, count are thrown away
-
- return buf_i;
- }
-
-}
diff --git a/src/utils/xor_buf.h b/src/utils/xor_buf.h
index 076877e02..2bf6ced59 100644
--- a/src/utils/xor_buf.h
+++ b/src/utils/xor_buf.h
@@ -67,24 +67,6 @@ inline void xor_buf(byte out[],
out[j] = in[j] ^ in2[j];
}
-/**
-* XOR values into buffer. Uses RLE compression
-* Intended for use in entropy sources to gather collected
-* data into a buffer to pass to an RNG.
-*/
-u32bit xor_into_buf(byte buf[], u32bit buf_i, u32bit length,
- const void* in_void, u32bit in_len);
-
-/**
-* XOR integer value (or something else, I guess) into buffer
-*/
-template<typename T>
-u32bit xor_into_buf(byte buf[], u32bit buf_i,
- u32bit length, const T& in)
- {
- return xor_into_buf(buf, buf_i, length, &in, sizeof(in));
- }
-
}
#endif