diff options
Diffstat (limited to 'src/entropy')
-rw-r--r-- | src/entropy/beos_stats/es_beos.cpp | 43 | ||||
-rw-r--r-- | src/entropy/beos_stats/es_beos.h | 3 | ||||
-rw-r--r-- | src/entropy/cryptoapi_rng/es_capi.cpp | 107 | ||||
-rw-r--r-- | src/entropy/cryptoapi_rng/es_capi.h | 9 | ||||
-rw-r--r-- | src/entropy/dev_random/es_dev.cpp | 48 | ||||
-rw-r--r-- | src/entropy/dev_random/es_dev.h | 16 | ||||
-rw-r--r-- | src/entropy/egd/es_egd.cpp | 128 | ||||
-rw-r--r-- | src/entropy/egd/es_egd.h | 10 | ||||
-rw-r--r-- | src/entropy/entropy_acc.cpp | 87 | ||||
-rw-r--r-- | src/entropy/entropy_src.h | 49 | ||||
-rw-r--r-- | src/entropy/info.txt | 1 | ||||
-rw-r--r-- | src/entropy/proc_walk/es_ftw.cpp | 42 | ||||
-rw-r--r-- | src/entropy/proc_walk/es_ftw.h | 9 | ||||
-rw-r--r-- | src/entropy/unix_procs/es_unix.cpp | 99 | ||||
-rw-r--r-- | src/entropy/unix_procs/es_unix.h | 20 | ||||
-rw-r--r-- | src/entropy/unix_procs/unix_cmd.cpp | 74 | ||||
-rw-r--r-- | src/entropy/unix_procs/unix_cmd.h | 20 | ||||
-rw-r--r-- | src/entropy/unix_procs/unix_src.cpp | 14 | ||||
-rw-r--r-- | src/entropy/win32_stats/es_win32.cpp | 167 | ||||
-rw-r--r-- | src/entropy/win32_stats/es_win32.h | 6 |
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); }; } |