diff options
Diffstat (limited to 'src/entropy')
24 files changed, 1445 insertions, 0 deletions
diff --git a/src/entropy/beos_stats/es_beos.cpp b/src/entropy/beos_stats/es_beos.cpp new file mode 100644 index 000000000..80d5605d0 --- /dev/null +++ b/src/entropy/beos_stats/es_beos.cpp @@ -0,0 +1,65 @@ +/************************************************* +* BeOS EntropySource Source File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#include <botan/es_beos.h> +#include <kernel/OS.h> +#include <kernel/image.h> +#include <interface/InterfaceDefs.h> + +namespace Botan { + +/************************************************* +* BeOS Fast Poll * +*************************************************/ +void BeOS_EntropySource::do_fast_poll() + { + system_info info_sys; + get_system_info(&info_sys); + add_bytes(&info_sys, sizeof(system_info)); + + key_info info_key; + get_key_info(&info_key); + add_bytes(&info_key, sizeof(key_info)); + + add_bytes(idle_time()); + } + +/************************************************* +* BeOS Slow Poll * +*************************************************/ +void BeOS_EntropySource::do_slow_poll() + { + team_info info_team; + int32 cookie_team = 0; + + while(get_next_team_info(&cookie_team, &info_team) == B_OK) + { + add_bytes(&info_team, sizeof(team_info)); + + team_id id = info_team.team; + int32 cookie = 0; + + thread_info info_thr; + while(get_next_thread_info(id, &cookie, &info_thr) == B_OK) + add_bytes(&info_thr, sizeof(thread_info)); + + cookie = 0; + image_info info_img; + while(get_next_image_info(id, &cookie, &info_img) == B_OK) + add_bytes(&info_img, sizeof(image_info)); + + cookie = 0; + sem_info info_sem; + while(get_next_sem_info(id, &cookie, &info_sem) == B_OK) + add_bytes(&info_sem, sizeof(sem_info)); + + cookie = 0; + area_info info_area; + while(get_next_area_info(id, &cookie, &info_area) == B_OK) + add_bytes(&info_area, sizeof(area_info)); + } + } + +} diff --git a/src/entropy/beos_stats/es_beos.h b/src/entropy/beos_stats/es_beos.h new file mode 100644 index 000000000..047939c8c --- /dev/null +++ b/src/entropy/beos_stats/es_beos.h @@ -0,0 +1,25 @@ +/************************************************* +* BeOS EntropySource Header File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#ifndef BOTAN_ENTROPY_SRC_BEOS_H__ +#define BOTAN_ENTROPY_SRC_BEOS_H__ + +#include <botan/buf_es.h> + +namespace Botan { + +/************************************************* +* BeOS Entropy Source * +*************************************************/ +class BeOS_EntropySource : public Buffered_EntropySource + { + private: + void do_fast_poll(); + void do_slow_poll(); + }; + +} + +#endif diff --git a/src/entropy/beos_stats/modinfo.txt b/src/entropy/beos_stats/modinfo.txt new file mode 100644 index 000000000..a7e62cfb3 --- /dev/null +++ b/src/entropy/beos_stats/modinfo.txt @@ -0,0 +1,19 @@ +realname "BeOS Entropy Source" + +define ENTROPY_SRC_BEOS +modset beos + +load_on auto + +<add> +es_beos.h +es_beos.cpp +</add> + +<os> +beos +</os> + +<libs> +beos -> root,be +</libs> diff --git a/src/entropy/cryptoapi_rng/es_capi.cpp b/src/entropy/cryptoapi_rng/es_capi.cpp new file mode 100644 index 000000000..7d1e0e753 --- /dev/null +++ b/src/entropy/cryptoapi_rng/es_capi.cpp @@ -0,0 +1,87 @@ +/************************************************* +* Win32 CryptoAPI EntropySource Source File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#include <botan/es_capi.h> +#include <botan/parsing.h> +#include <windows.h> +#include <wincrypt.h> + +namespace Botan { + +/************************************************* +* Gather Entropy from Win32 CAPI * +*************************************************/ +u32bit Win32_CAPI_EntropySource::slow_poll(byte output[], u32bit length) + { + + 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; + + 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; + } + return length; + } + +/************************************************* +* Gather Entropy from Win32 CAPI * +*************************************************/ +Win32_CAPI_EntropySource::Win32_CAPI_EntropySource(const std::string& provs) + { + std::vector<std::string> capi_provs = split_on(provs, ':'); + + for(u32bit j = 0; j != capi_provs.size(); ++j) + { + if(capi_provs[j] == "RSA_FULL") prov_types.push_back(PROV_RSA_FULL); + if(capi_provs[j] == "INTEL_SEC") prov_types.push_back(PROV_INTEL_SEC); + if(capi_provs[j] == "FORTEZZA") prov_types.push_back(PROV_FORTEZZA); + if(capi_provs[j] == "RNG") prov_types.push_back(PROV_RNG); + } + + if(prov_types.size() == 0) + prov_types.push_back(PROV_RSA_FULL); + } + +} diff --git a/src/entropy/cryptoapi_rng/es_capi.h b/src/entropy/cryptoapi_rng/es_capi.h new file mode 100644 index 000000000..68e42cf9c --- /dev/null +++ b/src/entropy/cryptoapi_rng/es_capi.h @@ -0,0 +1,28 @@ +/************************************************* +* Win32 CAPI EntropySource Header File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#ifndef BOTAN_ENTROPY_SRC_WIN32_CAPI_H__ +#define BOTAN_ENTROPY_SRC_WIN32_CAPI_H__ + +#include <botan/rng.h> +#include <vector> + +namespace Botan { + +/************************************************* +* Win32 CAPI Entropy Source * +*************************************************/ +class Win32_CAPI_EntropySource : public EntropySource + { + public: + u32bit slow_poll(byte[], u32bit); + Win32_CAPI_EntropySource(const std::string& = ""); + private: + std::vector<u64bit> prov_types; + }; + +} + +#endif diff --git a/src/entropy/cryptoapi_rng/modinfo.txt b/src/entropy/cryptoapi_rng/modinfo.txt new file mode 100644 index 000000000..40104664b --- /dev/null +++ b/src/entropy/cryptoapi_rng/modinfo.txt @@ -0,0 +1,21 @@ +realname "Win32 CryptoAPI Entropy Source" + +define ENTROPY_SRC_CAPI +load_on auto +modset win32 + +<add> +es_capi.h +es_capi.cpp +</add> + +# We'll just assume CAPI is there; this is OK except for 3.x, early versions +# of 95, and maybe NT 3.5 +<os> +windows +cygwin +</os> + +<libs> +windows -> advapi32 +</libs> diff --git a/src/entropy/dev_random/es_dev.cpp b/src/entropy/dev_random/es_dev.cpp new file mode 100644 index 000000000..310620716 --- /dev/null +++ b/src/entropy/dev_random/es_dev.cpp @@ -0,0 +1,112 @@ +/************************************************* +* Device EntropySource Source File * +* (C) 1999-2008 Jack Lloyd * +*************************************************/ + +#include <botan/es_dev.h> +#include <sys/select.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/fcntl.h> +#include <unistd.h> + +namespace Botan { + +namespace { + +/************************************************* +* A class handling reading from a device * +*************************************************/ +class Device_Reader + { + public: + typedef int fd_type; + + Device_Reader(fd_type device_fd) : fd(device_fd) {} + ~Device_Reader() { if(fd > 0) { ::close(fd); } } + u32bit get(byte out[], u32bit length); + + static fd_type open(const std::string& pathname); + private: + fd_type fd; + }; + +/************************************************* +* Read from a device file * +*************************************************/ +u32bit Device_Reader::get(byte out[], u32bit length) + { + if(fd < 0) + return 0; + + if(fd >= FD_SETSIZE) + return 0; + + const u32bit READ_WAIT_MS = 10; + + fd_set read_set; + FD_ZERO(&read_set); + FD_SET(fd, &read_set); + + struct ::timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = READ_WAIT_MS * 1000; + + if(::select(fd + 1, &read_set, 0, 0, &timeout) < 0) + return 0; + + if(!(FD_ISSET(fd, &read_set))) + return 0; + + const ssize_t got = ::read(fd, out, length); + if(got <= 0) + return 0; + + const u32bit ret = static_cast<u32bit>(got); + + if(ret > length) + return 0; + + return ret; + } + +/************************************************* +* Attempt to open a device * +*************************************************/ +int Device_Reader::open(const std::string& pathname) + { +#ifndef O_NONBLOCK + #define O_NONBLOCK 0 +#endif + +#ifndef O_NOCTTY + #define O_NOCTTY 0 +#endif + + const int flags = O_RDONLY | O_NONBLOCK | O_NOCTTY; + return ::open(pathname.c_str(), flags); + } + +} + +/************************************************* +* Gather entropy from a RNG device * +*************************************************/ +u32bit Device_EntropySource::slow_poll(byte output[], u32bit length) + { + u32bit read = 0; + + for(size_t j = 0; j != fsnames.size(); ++j) + { + Device_Reader reader(Device_Reader::open(fsnames[j])); + + read += reader.get(output + read, length - read); + + if(read == length) + break; + } + + return read; + } + +} diff --git a/src/entropy/dev_random/es_dev.h b/src/entropy/dev_random/es_dev.h new file mode 100644 index 000000000..21d28b9bb --- /dev/null +++ b/src/entropy/dev_random/es_dev.h @@ -0,0 +1,28 @@ +/************************************************* +* Device EntropySource Header File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#ifndef BOTAN_ENTROPY_SRC_DEVICE_H__ +#define BOTAN_ENTROPY_SRC_DEVICE_H__ + +#include <botan/rng.h> +#include <vector> + +namespace Botan { + +/************************************************* +* Device Based Entropy Source * +*************************************************/ +class Device_EntropySource : public EntropySource + { + public: + Device_EntropySource(const std::vector<std::string>& fs) : fsnames(fs) {} + u32bit slow_poll(byte[], u32bit); + private: + std::vector<std::string> fsnames; + }; + +} + +#endif diff --git a/src/entropy/dev_random/modinfo.txt b/src/entropy/dev_random/modinfo.txt new file mode 100644 index 000000000..6622886af --- /dev/null +++ b/src/entropy/dev_random/modinfo.txt @@ -0,0 +1,27 @@ +realname "RNG Device Reader" + +define ENTROPY_SRC_DEVICE + +load_on auto +modset unix + +<add> +es_dev.h +es_dev.cpp +</add> + +<os> +aix +beos +cygwin +darwin +freebsd +hpux +irix +linux +netbsd +openbsd +qnx +solaris +tru64 +</os> diff --git a/src/entropy/egd/es_egd.cpp b/src/entropy/egd/es_egd.cpp new file mode 100644 index 000000000..da4aaf847 --- /dev/null +++ b/src/entropy/egd/es_egd.cpp @@ -0,0 +1,76 @@ +/************************************************* +* EGD EntropySource Source File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#include <botan/es_egd.h> +#include <botan/bit_ops.h> +#include <botan/parsing.h> +#include <cstring> + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <unistd.h> + +#ifndef PF_LOCAL + #define PF_LOCAL PF_UNIX +#endif + +namespace Botan { + +/************************************************* +* Gather Entropy from EGD * +*************************************************/ +u32bit EGD_EntropySource::do_poll(byte output[], u32bit length, + const std::string& path) const + { + if(length > 128) + length = 128; + + 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"); + std::strcpy(addr.sun_path, path.c_str()); + + int fd = ::socket(addr.sun_family, SOCK_STREAM, 0); + if(fd == -1) return 0; + + int len = sizeof(addr.sun_family) + std::strlen(addr.sun_path) + 1; + if(::connect(fd, reinterpret_cast<struct ::sockaddr*>(&addr), len)) + { ::close(fd); return 0; } + + byte buffer[2]; + buffer[0] = 1; + buffer[1] = static_cast<byte>(length); + + if(::write(fd, buffer, 2) != 2) { ::close(fd); return 0; } + if(::read(fd, buffer, 1) != 1) { ::close(fd); return 0; } + + ssize_t count = ::read(fd, output, buffer[0]); + + if(count == -1) { close(fd); return 0; } + + ::close(fd); + + return count; + } + +/************************************************* +* Gather Entropy from EGD * +*************************************************/ +u32bit EGD_EntropySource::slow_poll(byte output[], u32bit length) + { + for(u32bit j = 0; j != paths.size(); j++) + { + u32bit got = do_poll(output, length, paths[j]); + if(got) + return got; + } + return 0; + } + +} diff --git a/src/entropy/egd/es_egd.h b/src/entropy/egd/es_egd.h new file mode 100644 index 000000000..ce6ba9521 --- /dev/null +++ b/src/entropy/egd/es_egd.h @@ -0,0 +1,30 @@ +/************************************************* +* EGD EntropySource Header File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#ifndef BOTAN_ENTROPY_SRC_EGD_H__ +#define BOTAN_ENTROPY_SRC_EGD_H__ + +#include <botan/rng.h> +#include <string> +#include <vector> + +namespace Botan { + +/************************************************* +* EGD Entropy Source * +*************************************************/ +class EGD_EntropySource : public EntropySource + { + public: + u32bit slow_poll(byte[], u32bit); + EGD_EntropySource(const std::vector<std::string>& p) : paths(p) {} + private: + u32bit do_poll(byte[], u32bit, const std::string&) const; + const std::vector<std::string> paths; + }; + +} + +#endif diff --git a/src/entropy/egd/modinfo.txt b/src/entropy/egd/modinfo.txt new file mode 100644 index 000000000..6b34f395c --- /dev/null +++ b/src/entropy/egd/modinfo.txt @@ -0,0 +1,31 @@ +realname "EGD Entropy Source" + +define ENTROPY_SRC_EGD + +load_on auto +modset unix + +<add> +es_egd.h +es_egd.cpp +</add> + +<libs> +solaris -> socket +qnx -> socket +</libs> + +<os> +aix +cygwin +darwin +freebsd +hpux +irix +linux +netbsd +openbsd +qnx +solaris +tru64 +</os> diff --git a/src/entropy/proc_walk/es_ftw.cpp b/src/entropy/proc_walk/es_ftw.cpp new file mode 100644 index 000000000..ec11378f8 --- /dev/null +++ b/src/entropy/proc_walk/es_ftw.cpp @@ -0,0 +1,147 @@ +/************************************************* +* FTW EntropySource Source File * +* (C) 1999-2008 Jack Lloyd * +*************************************************/ + +#include <botan/es_ftw.h> +#include <botan/util.h> +#include <cstring> +#include <deque> + +#ifndef _POSIX_C_SOURCE + #define _POSIX_C_SOURCE 199309 +#endif + +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <dirent.h> +#include <fcntl.h> + +namespace Botan { + +namespace { + +class Directory_Walker + { + public: + Directory_Walker(const std::string& root) { add_directory(root); } + ~Directory_Walker(); + + int next_fd(); + private: + void add_directory(const std::string&); + + std::deque<std::pair<DIR*, std::string> > dirs; + }; + +void Directory_Walker::add_directory(const std::string& dirname) + { + DIR* dir = ::opendir(dirname.c_str()); + if(dir) + dirs.push_back(std::make_pair(dir, dirname)); + } + +Directory_Walker::~Directory_Walker() + { + while(dirs.size()) + { + ::closedir(dirs[0].first); + dirs.pop_front(); + } + } + +int Directory_Walker::next_fd() + { + while(dirs.size()) + { + std::pair<DIR*, std::string> dirinfo = dirs[0]; + + struct dirent* entry = ::readdir(dirinfo.first); + + if(!entry) + { + ::closedir(dirinfo.first); + dirs.pop_front(); + continue; + } + + const std::string filename = entry->d_name; + + if(filename == "." || filename == "..") + continue; + + const std::string full_path = dirinfo.second + '/' + filename; + + struct stat stat_buf; + if(::lstat(full_path.c_str(), &stat_buf) == -1) + continue; + + if(S_ISDIR(stat_buf.st_mode)) + add_directory(full_path); + else if(S_ISREG(stat_buf.st_mode)) + { + int fd = ::open(full_path.c_str(), O_RDONLY | O_NOCTTY); + + if(fd > 0) + return fd; + } + } + + return -1; + } + +} + +/************************************************* +* FTW_EntropySource Constructor * +*************************************************/ +FTW_EntropySource::FTW_EntropySource(const std::string& p) : path(p) + { + } + +/************************************************* +* FTW Fast Poll * +*************************************************/ +void FTW_EntropySource::do_fast_poll() + { + poll(32*1024); + } + +/************************************************* +* FTW Slow Poll * +*************************************************/ +void FTW_EntropySource::do_slow_poll() + { + poll(256*1024); + } + +/************************************************* +* FTW Poll * +*************************************************/ +void FTW_EntropySource::poll(u32bit max_read) + { + Directory_Walker dir(path); + SecureVector<byte> read_buf(1024); + + u32bit read_so_far = 0; + while(read_so_far < max_read) + { + int fd = dir.next_fd(); + + if(fd == -1) + break; + + ssize_t got = ::read(fd, read_buf.begin(), read_buf.size()); + + if(got > 0) + { + add_bytes(read_buf, got); + read_so_far += got; + } + + ::close(fd); + } + } + +} diff --git a/src/entropy/proc_walk/es_ftw.h b/src/entropy/proc_walk/es_ftw.h new file mode 100644 index 000000000..a2229ff1f --- /dev/null +++ b/src/entropy/proc_walk/es_ftw.h @@ -0,0 +1,31 @@ +/************************************************* +* File Tree Walking EntropySource Header File * +* (C) 1999-2008 Jack Lloyd * +*************************************************/ + +#ifndef BOTAN_ENTROPY_SRC_FTW_H__ +#define BOTAN_ENTROPY_SRC_FTW_H__ + +#include <botan/buf_es.h> + +namespace Botan { + +/************************************************* +* File Tree Walking Entropy Source * +*************************************************/ +class FTW_EntropySource : public Buffered_EntropySource + { + public: + FTW_EntropySource(const std::string& root_dir); + private: + void do_fast_poll(); + void do_slow_poll(); + + void poll(u32bit max_read); + + const std::string path; + }; + +} + +#endif diff --git a/src/entropy/proc_walk/modinfo.txt b/src/entropy/proc_walk/modinfo.txt new file mode 100644 index 000000000..d932523fd --- /dev/null +++ b/src/entropy/proc_walk/modinfo.txt @@ -0,0 +1,29 @@ +realname "File Tree Walking Entropy Source" + +define ENTROPY_SRC_FTW + +load_on auto +modset unix + +<add> +es_ftw.h +es_ftw.cpp +</add> + +<os> +aix +cygwin +darwin +freebsd +hpux +irix +linux +openbsd +qnx +solaris +tru64 + +# Doesn't build on 2.0.2/x86 due to libc/libstdc++ header issues; no +# big deal since it has /dev/*random +#netbsd +</os> diff --git a/src/entropy/unix_procs/es_unix.cpp b/src/entropy/unix_procs/es_unix.cpp new file mode 100644 index 000000000..c503c20ae --- /dev/null +++ b/src/entropy/unix_procs/es_unix.cpp @@ -0,0 +1,112 @@ +/************************************************* +* Unix EntropySource Source File * +* (C) 1999-2008 Jack Lloyd * +*************************************************/ + +#include <botan/es_unix.h> +#include <botan/unix_cmd.h> +#include <botan/parsing.h> +#include <algorithm> +#include <sys/time.h> +#include <sys/stat.h> +#include <sys/resource.h> +#include <unistd.h> + +namespace Botan { + +namespace { + +/************************************************* +* 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::Unix_EntropySource(const std::vector<std::string>& path) : + PATH(path) + { + add_default_sources(sources); + } + +/************************************************* +* 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 * +*************************************************/ +void Unix_EntropySource::do_fast_poll() + { + const char* STAT_TARGETS[] = { "/", "/tmp", ".", "..", 0 }; + + for(u32bit j = 0; STAT_TARGETS[j]; j++) + { + struct stat statbuf; + clear_mem(&statbuf, 1); + ::stat(STAT_TARGETS[j], &statbuf); + add_bytes(&statbuf, sizeof(statbuf)); + } + + add_bytes(::getpid()); + add_bytes(::getppid()); + + add_bytes(::getuid()); + add_bytes(::getgid()); + add_bytes(::geteuid()); + add_bytes(::getegid()); + + add_bytes(::getpgrp()); + add_bytes(::getsid(0)); + + struct ::rusage usage; + + clear_mem(&usage, 1); + ::getrusage(RUSAGE_SELF, &usage); + add_bytes(&usage, sizeof(usage)); + + ::getrusage(RUSAGE_CHILDREN, &usage); + add_bytes(&usage, sizeof(usage)); + } + +/************************************************* +* Unix Slow Poll * +*************************************************/ +void Unix_EntropySource::do_slow_poll() + { + const u32bit TRY_TO_GET = 16 * 1024; + const u32bit MINIMAL_WORKING = 32; + + u32bit got = 0; + 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()); + add_bytes(buffer, this_loop); + got_from_src += this_loop; + } + + sources[j].working = (got_from_src >= MINIMAL_WORKING) ? true : false; + got += got_from_src; + + if(got >= TRY_TO_GET) + break; + } + } + +} diff --git a/src/entropy/unix_procs/es_unix.h b/src/entropy/unix_procs/es_unix.h new file mode 100644 index 000000000..d1b1d623e --- /dev/null +++ b/src/entropy/unix_procs/es_unix.h @@ -0,0 +1,35 @@ +/************************************************* +* Unix EntropySource Header File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#ifndef BOTAN_ENTROPY_SRC_UNIX_H__ +#define BOTAN_ENTROPY_SRC_UNIX_H__ + +#include <botan/buf_es.h> +#include <botan/unix_cmd.h> +#include <vector> + +namespace Botan { + +/************************************************* +* Unix Entropy Source * +*************************************************/ +class Unix_EntropySource : public Buffered_EntropySource + { + public: + 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>&); + + void do_fast_poll(); + void do_slow_poll(); + + const std::vector<std::string> PATH; + std::vector<Unix_Program> sources; + }; + +} + +#endif diff --git a/src/entropy/unix_procs/modinfo.txt b/src/entropy/unix_procs/modinfo.txt new file mode 100644 index 000000000..f16e21289 --- /dev/null +++ b/src/entropy/unix_procs/modinfo.txt @@ -0,0 +1,29 @@ +realname "Generic Unix Entropy Source" + +define ENTROPY_SRC_UNIX +modset unix,beos + +load_on auto + +<add> +es_unix.cpp +unix_src.cpp +unix_cmd.cpp +es_unix.h +unix_cmd.h +</add> + +<os> +aix +beos +cygwin +darwin +#freebsd +hpux +irix +linux +netbsd +qnx +solaris +tru64 +</os> diff --git a/src/entropy/unix_procs/unix_cmd.cpp b/src/entropy/unix_procs/unix_cmd.cpp new file mode 100644 index 000000000..32829b91b --- /dev/null +++ b/src/entropy/unix_procs/unix_cmd.cpp @@ -0,0 +1,240 @@ +/************************************************* +* Unix Command Execution Source File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#ifndef _XOPEN_SOURCE + #define _XOPEN_SOURCE 500 +#endif + +#ifndef _XOPEN_SOURCE_EXTENDED + #define _XOPEN_SOURCE_EXTENDED 1 +#endif + +#include <botan/unix_cmd.h> +#include <botan/parsing.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <stdlib.h> +#include <unistd.h> +#include <signal.h> + +namespace Botan { + +namespace { + +/************************************************* +* Attempt to execute the command * +************************************************/ +void do_exec(const std::vector<std::string>& arg_list, + const std::vector<std::string>& paths) + { + const u32bit args = arg_list.size() - 1; + + const char* arg1 = (args >= 1) ? arg_list[1].c_str() : 0; + const char* arg2 = (args >= 2) ? arg_list[2].c_str() : 0; + const char* arg3 = (args >= 3) ? arg_list[3].c_str() : 0; + const char* arg4 = (args >= 4) ? arg_list[4].c_str() : 0; + + for(u32bit j = 0; j != paths.size(); j++) + { + const std::string full_path = paths[j] + "/" + arg_list[0]; + const char* fsname = full_path.c_str(); + ::execl(fsname, fsname, arg1, arg2, arg3, arg4, NULL); + } + } + +} + +/************************************************* +* Local information about the pipe * +*************************************************/ +struct pipe_wrapper + { + int fd; + pid_t pid; + pipe_wrapper() { fd = -1; pid = 0; } + }; + +/************************************************* +* Read from the pipe * +*************************************************/ +u32bit DataSource_Command::read(byte buf[], u32bit length) + { + if(end_of_data()) + return 0; + + fd_set set; + FD_ZERO(&set); + FD_SET(pipe->fd, &set); + + struct ::timeval tv; + tv.tv_sec = 0; + tv.tv_usec = MAX_BLOCK_USECS; + + ssize_t got = 0; + if(::select(pipe->fd + 1, &set, 0, 0, &tv) == 1) + { + if(FD_ISSET(pipe->fd, &set)) + got = ::read(pipe->fd, buf, length); + } + + if(got <= 0) + { + shutdown_pipe(); + return 0; + } + + return static_cast<u32bit>(got); + } + +/************************************************* +* Peek at the pipe contents * +*************************************************/ +u32bit DataSource_Command::peek(byte[], u32bit, u32bit) const + { + if(end_of_data()) + throw Invalid_State("DataSource_Command: Cannot peek when out of data"); + throw Stream_IO_Error("Cannot peek/seek on a command pipe"); + } + +/************************************************* +* Check if we reached EOF * +*************************************************/ +bool DataSource_Command::end_of_data() const + { + return (pipe) ? false : true; + } + +/************************************************* +* Return the Unix file descriptor of the pipe * +*************************************************/ +int DataSource_Command::fd() const + { + if(!pipe) + return -1; + return pipe->fd; + } + +/************************************************* +* Return a human-readable ID for this stream * +*************************************************/ +std::string DataSource_Command::id() const + { + return "Unix command: " + arg_list[0]; + } + +/************************************************* +* Create the pipe * +*************************************************/ +void DataSource_Command::create_pipe(const std::vector<std::string>& paths) + { + bool found_something = false; + for(u32bit j = 0; j != paths.size(); j++) + { + const std::string full_path = paths[j] + "/" + arg_list[0]; + if(::access(full_path.c_str(), X_OK) == 0) + { + found_something = true; + break; + } + } + if(!found_something) + return; + + int pipe_fd[2]; + if(::pipe(pipe_fd) != 0) + return; + + pid_t pid = ::fork(); + + if(pid == -1) + { + ::close(pipe_fd[0]); + ::close(pipe_fd[1]); + } + else if(pid > 0) + { + pipe = new pipe_wrapper; + pipe->fd = pipe_fd[0]; + pipe->pid = pid; + ::close(pipe_fd[1]); + } + else + { + if(dup2(pipe_fd[1], STDOUT_FILENO) == -1) + ::exit(127); + if(close(pipe_fd[0]) != 0 || close(pipe_fd[1]) != 0) + ::exit(127); + if(close(STDERR_FILENO) != 0) + ::exit(127); + + do_exec(arg_list, paths); + ::exit(127); + } + } + +/************************************************* +* Shutdown the pipe * +*************************************************/ +void DataSource_Command::shutdown_pipe() + { + if(pipe) + { + pid_t reaped = waitpid(pipe->pid, 0, WNOHANG); + + if(reaped == 0) + { + kill(pipe->pid, SIGTERM); + + struct ::timeval tv; + tv.tv_sec = 0; + tv.tv_usec = KILL_WAIT; + select(0, 0, 0, 0, &tv); + + reaped = ::waitpid(pipe->pid, 0, WNOHANG); + + if(reaped == 0) + { + ::kill(pipe->pid, SIGKILL); + do + reaped = ::waitpid(pipe->pid, 0, 0); + while(reaped == -1); + } + } + + ::close(pipe->fd); + delete pipe; + pipe = 0; + } + } + +/************************************************* +* 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) + { + arg_list = split_on(prog_and_args, ' '); + + if(arg_list.size() == 0) + throw Invalid_Argument("DataSource_Command: No command given"); + if(arg_list.size() > 5) + throw Invalid_Argument("DataSource_Command: Too many args"); + + pipe = 0; + create_pipe(paths); + } + +/************************************************* +* DataSource_Command Destructor * +*************************************************/ +DataSource_Command::~DataSource_Command() + { + if(!end_of_data()) + shutdown_pipe(); + } + +} diff --git a/src/entropy/unix_procs/unix_cmd.h b/src/entropy/unix_procs/unix_cmd.h new file mode 100644 index 000000000..090dd8fdd --- /dev/null +++ b/src/entropy/unix_procs/unix_cmd.h @@ -0,0 +1,57 @@ +/************************************************* +* Unix Command Execution Header File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#ifndef BOTAN_UNIX_CMD_H__ +#define BOTAN_UNIX_CMD_H__ + +#include <botan/types.h> +#include <botan/data_src.h> +#include <string> +#include <vector> + +namespace Botan { + +/************************************************* +* Unix Program Info * +*************************************************/ +struct Unix_Program + { + Unix_Program(const char* n, u32bit p) + { name_and_args = n; priority = p; working = true; } + + std::string name_and_args; + u32bit priority; + bool working; + }; + +/************************************************* +* Command Output DataSource * +*************************************************/ +class DataSource_Command : public DataSource + { + public: + u32bit read(byte[], u32bit); + u32bit peek(byte[], u32bit, u32bit) const; + bool end_of_data() const; + std::string id() const; + + int fd() const; + + DataSource_Command(const std::string&, + const std::vector<std::string>& paths); + ~DataSource_Command(); + private: + void create_pipe(const std::vector<std::string>&); + void shutdown_pipe(); + + const u32bit MAX_BLOCK_USECS, KILL_WAIT; + + std::vector<std::string> arg_list; + struct pipe_wrapper* pipe; + }; + +} + +#endif diff --git a/src/entropy/unix_procs/unix_src.cpp b/src/entropy/unix_procs/unix_src.cpp new file mode 100644 index 000000000..9d44dbf4f --- /dev/null +++ b/src/entropy/unix_procs/unix_src.cpp @@ -0,0 +1,59 @@ +/************************************************* +* Program List for Unix_EntropySource * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#include <botan/es_unix.h> + +namespace Botan { + +/************************************************* +* Default Commands for Entropy Gathering * +*************************************************/ +void Unix_EntropySource::add_default_sources(std::vector<Unix_Program>& srcs) + { + srcs.push_back(Unix_Program("vmstat", 1)); + srcs.push_back(Unix_Program("vmstat -s", 1)); + srcs.push_back(Unix_Program("pfstat", 1)); + srcs.push_back(Unix_Program("netstat -in", 1)); + + srcs.push_back(Unix_Program("iostat", 2)); + srcs.push_back(Unix_Program("mpstat", 2)); + srcs.push_back(Unix_Program("nfsstat", 2)); + srcs.push_back(Unix_Program("portstat", 2)); + srcs.push_back(Unix_Program("arp -a -n", 2)); + srcs.push_back(Unix_Program("ifconfig -a", 2)); + srcs.push_back(Unix_Program("pstat -T", 2)); + srcs.push_back(Unix_Program("pstat -s", 2)); + srcs.push_back(Unix_Program("uname -a", 2)); + srcs.push_back(Unix_Program("uptime", 2)); + srcs.push_back(Unix_Program("ipcs -a", 2)); + srcs.push_back(Unix_Program("procinfo -a", 2)); + + srcs.push_back(Unix_Program("sysinfo", 3)); + srcs.push_back(Unix_Program("listarea", 3)); + srcs.push_back(Unix_Program("listdev", 3)); + + srcs.push_back(Unix_Program("who", 3)); + srcs.push_back(Unix_Program("finger", 3)); + srcs.push_back(Unix_Program("netstat -s", 3)); + srcs.push_back(Unix_Program("netstat -an", 3)); + srcs.push_back(Unix_Program("ps -A", 3)); + srcs.push_back(Unix_Program("mailstats", 3)); + srcs.push_back(Unix_Program("rpcinfo -p localhost", 3)); + + srcs.push_back(Unix_Program("dmesg", 4)); + srcs.push_back(Unix_Program("ls -alni /tmp", 4)); + srcs.push_back(Unix_Program("ls -alni /proc", 4)); + srcs.push_back(Unix_Program("df -l", 4)); + srcs.push_back(Unix_Program("last -5", 4)); + srcs.push_back(Unix_Program("pstat -f", 4)); + + srcs.push_back(Unix_Program("ps aux", 5)); + srcs.push_back(Unix_Program("ps -elf", 5)); + + srcs.push_back(Unix_Program("sar -A", 6)); + srcs.push_back(Unix_Program("lsof", 6)); + } + +} diff --git a/src/entropy/win32_stats/es_win32.cpp b/src/entropy/win32_stats/es_win32.cpp new file mode 100644 index 000000000..febed59c0 --- /dev/null +++ b/src/entropy/win32_stats/es_win32.cpp @@ -0,0 +1,109 @@ +/************************************************* +* Win32 EntropySource Source File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#include <botan/es_win32.h> +#include <windows.h> +#include <tlhelp32.h> + +namespace Botan { + +/************************************************* +* Win32 Slow Poll * +*************************************************/ +void Win32_EntropySource::do_slow_poll() + { + const u32bit MAX_ITEMS = 256; + + do_fast_poll(); + + 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)) \ + { \ + do \ + { \ + if(items++ > MAX_ITEMS) break; \ + add_bytes(&info, sizeof(info)); \ + } while(FUNC_NEXT(snapshot, &info)); \ + } \ + } + + TOOLHELP32_ITER(MODULEENTRY32, Module32First, Module32Next); + TOOLHELP32_ITER(PROCESSENTRY32, Process32First, Process32Next); + TOOLHELP32_ITER(THREADENTRY32, Thread32First, Thread32Next); + +#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)) + { + do + { + add_bytes(&heap_list, sizeof(HEAPLIST32)); + + 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)) + { + do + { + if(heap_objs_found++ > HEAP_OBJS_PER_LIST) + break; + add_bytes(&heap_entry, sizeof(HEAPENTRY32)); + } while(Heap32Next(&heap_entry)); + } + } while(Heap32ListNext(snapshot, &heap_list)); + } + + CloseHandle(snapshot); + } + +/************************************************* +* Win32 Fast Poll * +*************************************************/ +void Win32_EntropySource::do_fast_poll() + { + add_bytes(GetTickCount()); + add_bytes(GetMessagePos()); + add_bytes(GetMessageTime()); + add_bytes(GetInputState()); + add_bytes(GetCurrentProcessId()); + add_bytes(GetCurrentThreadId()); + + SYSTEM_INFO sys_info; + GetSystemInfo(&sys_info); + add_bytes(&sys_info, sizeof(sys_info)); + + MEMORYSTATUS mem_info; + GlobalMemoryStatus(&mem_info); + add_bytes(&mem_info, sizeof(mem_info)); + + POINT point; + GetCursorPos(&point); + add_bytes(&point, sizeof(point)); + GetCaretPos(&point); + add_bytes(&point, sizeof(point)); + + LARGE_INTEGER perf_counter; + QueryPerformanceCounter(&perf_counter); + add_bytes(&perf_counter, sizeof(perf_counter)); + } + +} diff --git a/src/entropy/win32_stats/es_win32.h b/src/entropy/win32_stats/es_win32.h new file mode 100644 index 000000000..02558b335 --- /dev/null +++ b/src/entropy/win32_stats/es_win32.h @@ -0,0 +1,25 @@ +/************************************************* +* Win32 EntropySource Header File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#ifndef BOTAN_ENTROPY_SRC_WIN32_H__ +#define BOTAN_ENTROPY_SRC_WIN32_H__ + +#include <botan/buf_es.h> + +namespace Botan { + +/************************************************* +* Win32 Entropy Source * +*************************************************/ +class Win32_EntropySource : public Buffered_EntropySource + { + private: + void do_fast_poll(); + void do_slow_poll(); + }; + +} + +#endif diff --git a/src/entropy/win32_stats/modinfo.txt b/src/entropy/win32_stats/modinfo.txt new file mode 100644 index 000000000..931760979 --- /dev/null +++ b/src/entropy/win32_stats/modinfo.txt @@ -0,0 +1,23 @@ +realname "Win32 Entropy Source" + +# Probably not much of an issue anymore +#note "This module will not run under NT4" + +define ENTROPY_SRC_WIN32 +modset win32 + +load_on auto + +<add> +es_win32.h +es_win32.cpp +</add> + +<os> +windows +cygwin +</os> + +<libs> +windows -> user32 +</libs> |