aboutsummaryrefslogtreecommitdiffstats
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/alloc_mmap/mmap_mem.cpp88
-rw-r--r--modules/alloc_mmap/mmap_mem.h27
-rw-r--r--modules/alloc_mmap/modinfo.txt20
-rw-r--r--modules/comp_bzip2/bzip2.cpp258
-rw-r--r--modules/comp_bzip2/bzip2.h58
-rw-r--r--modules/comp_bzip2/modinfo.txt14
-rw-r--r--modules/comp_zlib/modinfo.txt16
-rw-r--r--modules/comp_zlib/zlib.cpp266
-rw-r--r--modules/comp_zlib/zlib.h55
-rw-r--r--modules/eng_aep/aep_conn.cpp92
-rw-r--r--modules/eng_aep/aep_conn.h38
-rw-r--r--modules/eng_aep/aep_main.cpp191
-rw-r--r--modules/eng_aep/eng_aep.cpp352
-rw-r--r--modules/eng_aep/eng_aep.h51
-rw-r--r--modules/eng_aep/es_aep.h24
-rw-r--r--modules/eng_aep/hw_aep.h48
-rw-r--r--modules/eng_aep/modinfo.txt22
-rw-r--r--modules/eng_gmp/eng_gmp.cpp377
-rw-r--r--modules/eng_gmp/eng_gmp.h43
-rw-r--r--modules/eng_gmp/gmp_mem.cpp60
-rw-r--r--modules/eng_gmp/gmp_powm.cpp51
-rw-r--r--modules/eng_gmp/gmp_wrap.cpp96
-rw-r--r--modules/eng_gmp/gmp_wrap.h36
-rw-r--r--modules/eng_gmp/modinfo.txt19
-rw-r--r--modules/eng_ossl/bn_powm.cpp52
-rw-r--r--modules/eng_ossl/bn_wrap.cpp114
-rw-r--r--modules/eng_ossl/bn_wrap.h51
-rw-r--r--modules/eng_ossl/eng_ossl.cpp374
-rw-r--r--modules/eng_ossl/eng_ossl.h40
-rw-r--r--modules/eng_ossl/modinfo.txt21
-rw-r--r--modules/eng_ossl/ossl_bc.cpp204
-rw-r--r--modules/eng_ossl/ossl_md.cpp121
-rw-r--r--modules/eng_ossl/ossl_rc4.cpp92
-rw-r--r--modules/es_beos/es_beos.cpp65
-rw-r--r--modules/es_beos/es_beos.h25
-rw-r--r--modules/es_beos/modinfo.txt14
-rw-r--r--modules/es_capi/es_capi.cpp109
-rw-r--r--modules/es_capi/es_capi.h28
-rw-r--r--modules/es_capi/modinfo.txt17
-rw-r--r--modules/es_egd/es_egd.cpp91
-rw-r--r--modules/es_egd/es_egd.h30
-rw-r--r--modules/es_egd/modinfo.txt26
-rw-r--r--modules/es_ftw/es_ftw.cpp110
-rw-r--r--modules/es_ftw/es_ftw.h31
-rw-r--r--modules/es_ftw/modinfo.txt24
-rw-r--r--modules/es_unix/es_unix.cpp105
-rw-r--r--modules/es_unix/es_unix.h35
-rw-r--r--modules/es_unix/modinfo.txt25
-rw-r--r--modules/es_unix/unix_cmd.cpp241
-rw-r--r--modules/es_unix/unix_cmd.h56
-rw-r--r--modules/es_unix/unix_src.cpp59
-rw-r--r--modules/es_win32/es_win32.cpp105
-rw-r--r--modules/es_win32/es_win32.h25
-rw-r--r--modules/es_win32/modinfo.txt18
-rw-r--r--modules/fd_unix/fd_unix.cpp50
-rw-r--r--modules/fd_unix/fd_unix.h21
-rw-r--r--modules/fd_unix/modinfo.txt22
-rw-r--r--modules/ml_unix/mlock.cpp33
-rw-r--r--modules/ml_unix/modinfo.txt21
-rw-r--r--modules/ml_win32/mlock.cpp27
-rw-r--r--modules/ml_win32/modinfo.txt8
-rw-r--r--modules/mod_qt/modinfo.txt19
-rw-r--r--modules/mod_qt/mux_qt.cpp56
-rw-r--r--modules/mod_qt/mux_qt.h31
-rw-r--r--modules/mod_qt/types.h28
-rw-r--r--modules/mp_amd64/modinfo.txt15
-rw-r--r--modules/mp_amd64/mp_asm.h84
-rw-r--r--modules/mp_amd64/mp_asmi.h174
-rw-r--r--modules/mp_asm64/modinfo.txt23
-rw-r--r--modules/mp_asm64/mp_asm.h119
-rw-r--r--modules/mp_ia32/modinfo.txt15
-rw-r--r--modules/mp_ia32/mp_asm.h88
-rw-r--r--modules/mp_ia32/mp_asmi.h174
-rw-r--r--modules/mp_ia32_msvc/modinfo.txt13
-rw-r--r--modules/mp_ia32_msvc/mp_asmi.h486
-rw-r--r--modules/mux_pthr/modinfo.txt25
-rw-r--r--modules/mux_pthr/mux_pthr.cpp62
-rw-r--r--modules/mux_pthr/mux_pthr.h24
-rw-r--r--modules/mux_win32/modinfo.txt11
-rw-r--r--modules/mux_win32/mux_win32.cpp39
-rw-r--r--modules/mux_win32/mux_win32.h23
-rw-r--r--modules/tm_hard/modinfo.txt24
-rw-r--r--modules/tm_hard/tm_hard.cpp41
-rw-r--r--modules/tm_hard/tm_hard.h24
-rw-r--r--modules/tm_posix/modinfo.txt19
-rw-r--r--modules/tm_posix/tm_posix.cpp31
-rw-r--r--modules/tm_posix/tm_posix.h24
-rw-r--r--modules/tm_unix/modinfo.txt22
-rw-r--r--modules/tm_unix/tm_unix.cpp22
-rw-r--r--modules/tm_unix/tm_unix.h24
-rw-r--r--modules/tm_win32/modinfo.txt15
-rw-r--r--modules/tm_win32/tm_win32.cpp21
-rw-r--r--modules/tm_win32/tm_win32.h24
93 files changed, 6592 insertions, 0 deletions
diff --git a/modules/alloc_mmap/mmap_mem.cpp b/modules/alloc_mmap/mmap_mem.cpp
new file mode 100644
index 000000000..d2e66d0cc
--- /dev/null
+++ b/modules/alloc_mmap/mmap_mem.cpp
@@ -0,0 +1,88 @@
+/*************************************************
+* Memory Mapping Allocator Source File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#include <botan/mmap_mem.h>
+#include <cstring>
+
+#ifndef _XOPEN_SOURCE
+ #define _XOPEN_SOURCE 500
+#endif
+
+#ifndef _XOPEN_SOURCE_EXTENDED
+ #define _XOPEN_SOURCE_EXTENDED 1
+#endif
+
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+
+#ifndef MAP_FAILED
+ #define MAP_FAILED -1
+#endif
+
+namespace Botan {
+
+/*************************************************
+* Memory Map a File into Memory *
+*************************************************/
+void* MemoryMapping_Allocator::alloc_block(u32bit n)
+ {
+ const std::string path = "/tmp/botan_XXXXXX";
+
+ char* filepath = new char[path.length() + 1];
+ std::strcpy(filepath, path.c_str());
+
+ mode_t old_umask = umask(077);
+ int fd = mkstemp(filepath);
+ umask(old_umask);
+
+ if(fd == -1)
+ throw Exception("MemoryMapping_Allocator: Could not create file");
+ if(unlink(filepath))
+ throw Exception("MemoryMapping_Allocator: Could not unlink file " +
+ std::string(filepath));
+ delete[] filepath;
+
+ lseek(fd, n-1, SEEK_SET);
+ if(write(fd, "\0", 1) != 1)
+ throw Exception("MemoryMapping_Allocator: Could not write to file");
+ void* ptr = mmap(0, n, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if(ptr == (void*)MAP_FAILED)
+ throw Exception("MemoryMapping_Allocator: Could not map file");
+ if(close(fd))
+ throw Exception("MemoryMapping_Allocator: Could not close file");
+
+ return ptr;
+ }
+
+/*************************************************
+* Remove a Memory Mapping *
+*************************************************/
+void MemoryMapping_Allocator::dealloc_block(void* ptr, u32bit n)
+ {
+ if(ptr == 0) return;
+
+ const u32bit OVERWRITE_PASSES = 12;
+ const byte PATTERNS[] = { 0x00, 0xFF, 0xAA, 0x55, 0x73, 0x8C, 0x5F, 0xA0,
+ 0x6E, 0x91, 0x30, 0xCF, 0xD3, 0x2C, 0xAC, 0x53 };
+
+ for(u32bit j = 0; j != OVERWRITE_PASSES; j++)
+ {
+ std::memset(ptr, PATTERNS[j % sizeof(PATTERNS)], n);
+ if(msync(ptr, n, MS_SYNC))
+ throw Exception("MemoryMapping_Allocator: Sync operation failed");
+ }
+ std::memset(ptr, 0, n);
+ if(msync(ptr, n, MS_SYNC))
+ throw Exception("MemoryMapping_Allocator: Sync operation failed");
+
+ if(munmap(ptr, n))
+ throw Exception("MemoryMapping_Allocator: Could not unmap file");
+ }
+
+}
diff --git a/modules/alloc_mmap/mmap_mem.h b/modules/alloc_mmap/mmap_mem.h
new file mode 100644
index 000000000..0530e54be
--- /dev/null
+++ b/modules/alloc_mmap/mmap_mem.h
@@ -0,0 +1,27 @@
+/*************************************************
+* Memory Mapping Allocator Header File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#ifndef BOTAN_EXT_MMAP_ALLOCATOR_H__
+#define BOTAN_EXT_MMAP_ALLOCATOR_H__
+
+#include <botan/mem_pool.h>
+
+namespace Botan {
+
+/*************************************************
+* Memory Mapping Allocator *
+*************************************************/
+class MemoryMapping_Allocator : public Pooling_Allocator
+ {
+ public:
+ MemoryMapping_Allocator() : Pooling_Allocator(64*1024, false) {}
+ private:
+ void* alloc_block(u32bit);
+ void dealloc_block(void*, u32bit);
+ };
+
+}
+
+#endif
diff --git a/modules/alloc_mmap/modinfo.txt b/modules/alloc_mmap/modinfo.txt
new file mode 100644
index 000000000..f51e3cb68
--- /dev/null
+++ b/modules/alloc_mmap/modinfo.txt
@@ -0,0 +1,20 @@
+realname "Disk Based Allocation System"
+
+define ALLOC_MMAP
+
+add_file mmap_mem.cpp
+add_file mmap_mem.h
+
+<os>
+linux
+freebsd
+openbsd
+netbsd
+solaris
+qnx
+darwin
+tru64
+
+# Only without -ansi, otherwise can't get mkstemp
+#cygwin
+</os>
diff --git a/modules/comp_bzip2/bzip2.cpp b/modules/comp_bzip2/bzip2.cpp
new file mode 100644
index 000000000..e5934b635
--- /dev/null
+++ b/modules/comp_bzip2/bzip2.cpp
@@ -0,0 +1,258 @@
+/*************************************************
+* Bzip Compressor Source File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#include <botan/bzip2.h>
+#include <map>
+#include <cstring>
+#define BZ_NO_STDIO
+#include <bzlib.h>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* Allocation Information for Bzip *
+*************************************************/
+class Bzip_Alloc_Info
+ {
+ public:
+ std::map<void*, u32bit> current_allocs;
+ Allocator* alloc;
+
+ Bzip_Alloc_Info() { alloc = get_allocator(); }
+ };
+
+/*************************************************
+* Allocation Function for Bzip *
+*************************************************/
+void* bzip_malloc(void* info_ptr, int n, int size)
+ {
+ Bzip_Alloc_Info* info = static_cast<Bzip_Alloc_Info*>(info_ptr);
+ void* ptr = info->alloc->allocate(n * size);
+ info->current_allocs[ptr] = n * size;
+ return ptr;
+ }
+
+/*************************************************
+* Allocation Function for Bzip *
+*************************************************/
+void bzip_free(void* info_ptr, void* ptr)
+ {
+ Bzip_Alloc_Info* info = static_cast<Bzip_Alloc_Info*>(info_ptr);
+ std::map<void*, u32bit>::const_iterator i = info->current_allocs.find(ptr);
+ if(i == info->current_allocs.end())
+ throw Invalid_Argument("bzip_free: Got pointer not allocated by us");
+ info->alloc->deallocate(ptr, i->second);
+ }
+
+}
+
+/*************************************************
+* Wrapper Type for Bzip2 Stream *
+*************************************************/
+class Bzip_Stream
+ {
+ public:
+ bz_stream stream;
+
+ Bzip_Stream()
+ {
+ std::memset(&stream, 0, sizeof(bz_stream));
+ stream.bzalloc = bzip_malloc;
+ stream.bzfree = bzip_free;
+ stream.opaque = new Bzip_Alloc_Info;
+ }
+ ~Bzip_Stream()
+ {
+ Bzip_Alloc_Info* info = static_cast<Bzip_Alloc_Info*>(stream.opaque);
+ delete info;
+ std::memset(&stream, 0, sizeof(bz_stream));
+ }
+ };
+
+/*************************************************
+* Bzip_Compression Constructor *
+*************************************************/
+Bzip_Compression::Bzip_Compression(u32bit l) :
+ level((l >= 9) ? 9 : l), buffer(DEFAULT_BUFFERSIZE)
+ {
+ bz = 0;
+ }
+
+/*************************************************
+* Start Compressing with Bzip *
+*************************************************/
+void Bzip_Compression::start_msg()
+ {
+ clear();
+ bz = new Bzip_Stream;
+ if(BZ2_bzCompressInit(&(bz->stream), level, 0, 0) != BZ_OK)
+ throw Exception("Bzip_Compression: Memory allocation error");
+ }
+
+/*************************************************
+* Compress Input with Bzip *
+*************************************************/
+void Bzip_Compression::write(const byte input[], u32bit length)
+ {
+ bz->stream.next_in = (char*)input;
+ bz->stream.avail_in = length;
+
+ while(bz->stream.avail_in != 0)
+ {
+ bz->stream.next_out = (char*)buffer.begin();
+ bz->stream.avail_out = buffer.size();
+ BZ2_bzCompress(&(bz->stream), BZ_RUN);
+ send(buffer, buffer.size() - bz->stream.avail_out);
+ }
+ }
+
+/*************************************************
+* Finish Compressing with Bzip *
+*************************************************/
+void Bzip_Compression::end_msg()
+ {
+ bz->stream.next_in = 0;
+ bz->stream.avail_in = 0;
+
+ int rc = BZ_OK;
+ while(rc != BZ_STREAM_END)
+ {
+ bz->stream.next_out = (char*)buffer.begin();
+ bz->stream.avail_out = buffer.size();
+ rc = BZ2_bzCompress(&(bz->stream), BZ_FINISH);
+ send(buffer, buffer.size() - bz->stream.avail_out);
+ }
+ clear();
+ }
+
+/*************************************************
+* Flush the Bzip Compressor *
+*************************************************/
+void Bzip_Compression::flush()
+ {
+ bz->stream.next_in = 0;
+ bz->stream.avail_in = 0;
+
+ int rc = BZ_OK;
+ while(rc != BZ_RUN_OK)
+ {
+ bz->stream.next_out = (char*)buffer.begin();
+ bz->stream.avail_out = buffer.size();
+ rc = BZ2_bzCompress(&(bz->stream), BZ_FLUSH);
+ send(buffer, buffer.size() - bz->stream.avail_out);
+ }
+ }
+
+/*************************************************
+* Clean up Compression Context *
+*************************************************/
+void Bzip_Compression::clear()
+ {
+ if(!bz) return;
+ BZ2_bzCompressEnd(&(bz->stream));
+ delete bz;
+ bz = 0;
+ }
+
+/*************************************************
+* Bzip_Decompression Constructor *
+*************************************************/
+Bzip_Decompression::Bzip_Decompression(bool s) :
+ small_mem(s), buffer(DEFAULT_BUFFERSIZE)
+ {
+ no_writes = true;
+ bz = 0;
+ }
+
+/*************************************************
+* Decompress Input with Bzip *
+*************************************************/
+void Bzip_Decompression::write(const byte input[], u32bit length)
+ {
+ if(length) no_writes = false;
+ bz->stream.next_in = (char*)input;
+ bz->stream.avail_in = length;
+
+ while(bz->stream.avail_in != 0)
+ {
+ bz->stream.next_out = (char*)buffer.begin();
+ bz->stream.avail_out = buffer.size();
+
+ int rc = BZ2_bzDecompress(&(bz->stream));
+ if(rc != BZ_OK && rc != BZ_STREAM_END)
+ {
+ clear();
+ if(rc == BZ_DATA_ERROR)
+ throw Decoding_Error("Bzip_Decompression: Data integrity error");
+ if(rc == BZ_DATA_ERROR_MAGIC)
+ throw Decoding_Error("Bzip_Decompression: Invalid input");
+ if(rc == BZ_MEM_ERROR)
+ throw Exception("Bzip_Decompression: Memory allocation error");
+ throw Exception("Bzip_Decompression: Unknown decompress error");
+ }
+ send(buffer, buffer.size() - bz->stream.avail_out);
+ if(rc == BZ_STREAM_END)
+ {
+ u32bit read_from_block = length - bz->stream.avail_in;
+ start_msg();
+ bz->stream.next_in = (char*)input + read_from_block;
+ bz->stream.avail_in = length - read_from_block;
+ input += read_from_block;
+ length -= read_from_block;
+ }
+ }
+ }
+
+/*************************************************
+* Start Decompressing with Bzip *
+*************************************************/
+void Bzip_Decompression::start_msg()
+ {
+ clear();
+ bz = new Bzip_Stream;
+ if(BZ2_bzDecompressInit(&(bz->stream), 0, small_mem) != BZ_OK)
+ throw Exception("Bzip_Decompression: Memory allocation error");
+ no_writes = true;
+ }
+
+/*************************************************
+* Finish Decompressing with Bzip *
+*************************************************/
+void Bzip_Decompression::end_msg()
+ {
+ if(no_writes) return;
+ bz->stream.next_in = 0;
+ bz->stream.avail_in = 0;
+
+ int rc = BZ_OK;
+ while(rc != BZ_STREAM_END)
+ {
+ bz->stream.next_out = (char*)buffer.begin();
+ bz->stream.avail_out = buffer.size();
+ rc = BZ2_bzDecompress(&(bz->stream));
+ if(rc != BZ_OK && rc != BZ_STREAM_END)
+ {
+ clear();
+ throw Exception("Bzip_Decompression: Error finalizing decompression");
+ }
+ send(buffer, buffer.size() - bz->stream.avail_out);
+ }
+ clear();
+ }
+
+/*************************************************
+* Clean up Decompression Context *
+*************************************************/
+void Bzip_Decompression::clear()
+ {
+ if(!bz) return;
+ BZ2_bzDecompressEnd(&(bz->stream));
+ delete bz;
+ bz = 0;
+ }
+
+}
diff --git a/modules/comp_bzip2/bzip2.h b/modules/comp_bzip2/bzip2.h
new file mode 100644
index 000000000..40bfd1a77
--- /dev/null
+++ b/modules/comp_bzip2/bzip2.h
@@ -0,0 +1,58 @@
+/*************************************************
+* Bzip Compressor Header File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#ifndef BOTAN_EXT_BZIP2_H__
+#define BOTAN_EXT_BZIP2_H__
+
+#include <botan/filter.h>
+
+namespace Botan {
+
+/*************************************************
+* Bzip Compression Filter *
+*************************************************/
+class Bzip_Compression : public Filter
+ {
+ public:
+ void write(const byte input[], u32bit length);
+ void start_msg();
+ void end_msg();
+
+ void flush();
+
+ Bzip_Compression(u32bit = 9);
+ ~Bzip_Compression() { clear(); }
+ private:
+ void clear();
+
+ const u32bit level;
+ SecureVector<byte> buffer;
+ class Bzip_Stream* bz;
+ };
+
+/*************************************************
+* Bzip Decompression Filter *
+*************************************************/
+class Bzip_Decompression : public Filter
+ {
+ public:
+ void write(const byte input[], u32bit length);
+ void start_msg();
+ void end_msg();
+
+ Bzip_Decompression(bool = false);
+ ~Bzip_Decompression() { clear(); }
+ private:
+ void clear();
+
+ const bool small_mem;
+ SecureVector<byte> buffer;
+ class Bzip_Stream* bz;
+ bool no_writes;
+ };
+
+}
+
+#endif
diff --git a/modules/comp_bzip2/modinfo.txt b/modules/comp_bzip2/modinfo.txt
new file mode 100644
index 000000000..3f1428e2c
--- /dev/null
+++ b/modules/comp_bzip2/modinfo.txt
@@ -0,0 +1,14 @@
+# This module was written by Peter J. Jones
+
+uses_external_libs
+
+realname "Bzip2 Compressor"
+
+define COMPRESSOR_BZIP2
+
+add_file bzip2.h
+add_file bzip2.cpp
+
+<libs>
+all -> bz2
+</libs>
diff --git a/modules/comp_zlib/modinfo.txt b/modules/comp_zlib/modinfo.txt
new file mode 100644
index 000000000..32acec513
--- /dev/null
+++ b/modules/comp_zlib/modinfo.txt
@@ -0,0 +1,16 @@
+realname "Zlib Compressor"
+#realname "Zlib/Gzip Compressor"
+
+uses_external_libs
+
+define COMPRESSOR_ZLIB
+#define COMPRESSOR_GZIP
+
+add_file zlib.h
+add_file zlib.cpp
+#add_file gzip.h
+#add_file gzip.cpp
+
+<libs>
+all -> z
+</libs>
diff --git a/modules/comp_zlib/zlib.cpp b/modules/comp_zlib/zlib.cpp
new file mode 100644
index 000000000..8bbafcea2
--- /dev/null
+++ b/modules/comp_zlib/zlib.cpp
@@ -0,0 +1,266 @@
+/*************************************************
+* Zlib Compressor Source File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#include <botan/zlib.h>
+#include <cstring>
+#include <map>
+#include <zlib.h>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* Allocation Information for Zlib *
+*************************************************/
+class Zlib_Alloc_Info
+ {
+ public:
+ std::map<void*, u32bit> current_allocs;
+ Allocator* alloc;
+
+ Zlib_Alloc_Info() { alloc = get_allocator(); }
+ };
+
+/*************************************************
+* Allocation Function for Zlib *
+*************************************************/
+void* zlib_malloc(void* info_ptr, unsigned int n, unsigned int size)
+ {
+ Zlib_Alloc_Info* info = static_cast<Zlib_Alloc_Info*>(info_ptr);
+ void* ptr = info->alloc->allocate(n * size);
+ info->current_allocs[ptr] = n * size;
+ return ptr;
+ }
+
+/*************************************************
+* Allocation Function for Zlib *
+*************************************************/
+void zlib_free(void* info_ptr, void* ptr)
+ {
+ Zlib_Alloc_Info* info = static_cast<Zlib_Alloc_Info*>(info_ptr);
+ std::map<void*, u32bit>::const_iterator i = info->current_allocs.find(ptr);
+ if(i == info->current_allocs.end())
+ throw Invalid_Argument("zlib_free: Got pointer not allocated by us");
+ info->alloc->deallocate(ptr, i->second);
+ }
+
+}
+
+/*************************************************
+* Wrapper Type for Zlib z_stream *
+*************************************************/
+class Zlib_Stream
+ {
+ public:
+ z_stream stream;
+
+ Zlib_Stream()
+ {
+ std::memset(&stream, 0, sizeof(z_stream));
+ stream.zalloc = zlib_malloc;
+ stream.zfree = zlib_free;
+ stream.opaque = new Zlib_Alloc_Info;
+ }
+ ~Zlib_Stream()
+ {
+ Zlib_Alloc_Info* info = static_cast<Zlib_Alloc_Info*>(stream.opaque);
+ delete info;
+ std::memset(&stream, 0, sizeof(z_stream));
+ }
+ };
+
+/*************************************************
+* Zlib_Compression Constructor *
+*************************************************/
+Zlib_Compression::Zlib_Compression(u32bit l) :
+ level((l >= 9) ? 9 : l), buffer(DEFAULT_BUFFERSIZE)
+ {
+ zlib = 0;
+ }
+
+/*************************************************
+* Start Compressing with Zlib *
+*************************************************/
+void Zlib_Compression::start_msg()
+ {
+ clear();
+ zlib = new Zlib_Stream;
+ if(deflateInit(&(zlib->stream), level) != Z_OK)
+ throw Exception("Zlib_Compression: Memory allocation error");
+ }
+
+/*************************************************
+* Compress Input with Zlib *
+*************************************************/
+void Zlib_Compression::write(const byte input[], u32bit length)
+ {
+ zlib->stream.next_in = (Bytef*)input;
+ zlib->stream.avail_in = length;
+
+ while(zlib->stream.avail_in != 0)
+ {
+ zlib->stream.next_out = (Bytef*)buffer.begin();
+ zlib->stream.avail_out = buffer.size();
+ deflate(&(zlib->stream), Z_NO_FLUSH);
+ send(buffer.begin(), buffer.size() - zlib->stream.avail_out);
+ }
+ }
+
+/*************************************************
+* Finish Compressing with Zlib *
+*************************************************/
+void Zlib_Compression::end_msg()
+ {
+ zlib->stream.next_in = 0;
+ zlib->stream.avail_in = 0;
+
+ int rc = Z_OK;
+ while(rc != Z_STREAM_END)
+ {
+ zlib->stream.next_out = (Bytef*)buffer.begin();
+ zlib->stream.avail_out = buffer.size();
+ rc = deflate(&(zlib->stream), Z_FINISH);
+ send(buffer.begin(), buffer.size() - zlib->stream.avail_out);
+ }
+ clear();
+ }
+
+/*************************************************
+* Flush the Zlib Compressor *
+*************************************************/
+void Zlib_Compression::flush()
+ {
+ zlib->stream.next_in = 0;
+ zlib->stream.avail_in = 0;
+
+ while(true)
+ {
+ zlib->stream.next_out = (Bytef*)buffer.begin();
+ zlib->stream.avail_out = buffer.size();
+ deflate(&(zlib->stream), Z_FULL_FLUSH);
+ send(buffer.begin(), buffer.size() - zlib->stream.avail_out);
+ if(zlib->stream.avail_out == buffer.size()) break;
+ }
+ }
+
+/*************************************************
+* Clean up Compression Context *
+*************************************************/
+void Zlib_Compression::clear()
+ {
+ if(zlib)
+ {
+ deflateEnd(&(zlib->stream));
+ delete zlib;
+ zlib = 0;
+ }
+
+ buffer.clear();
+ }
+
+/*************************************************
+* Zlib_Decompression Constructor *
+*************************************************/
+Zlib_Decompression::Zlib_Decompression() : buffer(DEFAULT_BUFFERSIZE)
+ {
+ zlib = 0;
+ no_writes = true;
+ }
+
+/*************************************************
+* Start Decompressing with Zlib *
+*************************************************/
+void Zlib_Decompression::start_msg()
+ {
+ clear();
+ zlib = new Zlib_Stream;
+ if(inflateInit(&(zlib->stream)) != Z_OK)
+ throw Exception("Zlib_Decompression: Memory allocation error");
+ }
+
+/*************************************************
+* Decompress Input with Zlib *
+*************************************************/
+void Zlib_Decompression::write(const byte input[], u32bit length)
+ {
+ if(length) no_writes = false;
+
+ zlib->stream.next_in = (Bytef*)input;
+ zlib->stream.avail_in = length;
+
+ while(zlib->stream.avail_in != 0)
+ {
+ zlib->stream.next_out = (Bytef*)buffer.begin();
+ zlib->stream.avail_out = buffer.size();
+
+ int rc = inflate(&(zlib->stream), Z_SYNC_FLUSH);
+ if(rc != Z_OK && rc != Z_STREAM_END)
+ {
+ clear();
+ if(rc == Z_DATA_ERROR)
+ throw Decoding_Error("Zlib_Decompression: Data integrity error");
+ if(rc == Z_NEED_DICT)
+ throw Decoding_Error("Zlib_Decompression: Need preset dictionary");
+ if(rc == Z_MEM_ERROR)
+ throw Exception("Zlib_Decompression: Memory allocation error");
+ throw Exception("Zlib_Decompression: Unknown decompress error");
+ }
+ send(buffer.begin(), buffer.size() - zlib->stream.avail_out);
+ if(rc == Z_STREAM_END)
+ {
+ u32bit read_from_block = length - zlib->stream.avail_in;
+ start_msg();
+ zlib->stream.next_in = (Bytef*)input + read_from_block;
+ zlib->stream.avail_in = length - read_from_block;
+ input += read_from_block;
+ length -= read_from_block;
+ }
+ }
+ }
+
+/*************************************************
+* Finish Decompressing with Zlib *
+*************************************************/
+void Zlib_Decompression::end_msg()
+ {
+ if(no_writes) return;
+ zlib->stream.next_in = 0;
+ zlib->stream.avail_in = 0;
+
+ int rc = Z_OK;
+ while(rc != Z_STREAM_END)
+ {
+ zlib->stream.next_out = (Bytef*)buffer.begin();
+ zlib->stream.avail_out = buffer.size();
+ rc = inflate(&(zlib->stream), Z_SYNC_FLUSH);
+ if(rc != Z_OK && rc != Z_STREAM_END)
+ {
+ clear();
+ throw Exception("Zlib_Decompression: Error finalizing decompression");
+ }
+ send(buffer.begin(), buffer.size() - zlib->stream.avail_out);
+ }
+ clear();
+ }
+
+/*************************************************
+* Clean up Decompression Context *
+*************************************************/
+void Zlib_Decompression::clear()
+ {
+ no_writes = true;
+
+ if(zlib)
+ {
+ inflateEnd(&(zlib->stream));
+ delete zlib;
+ zlib = 0;
+ }
+
+ buffer.clear();
+ }
+
+}
diff --git a/modules/comp_zlib/zlib.h b/modules/comp_zlib/zlib.h
new file mode 100644
index 000000000..1557afaab
--- /dev/null
+++ b/modules/comp_zlib/zlib.h
@@ -0,0 +1,55 @@
+/*************************************************
+* Zlib Compressor Header File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#ifndef BOTAN_EXT_ZLIB_H__
+#define BOTAN_EXT_ZLIB_H__
+
+#include <botan/filter.h>
+
+namespace Botan {
+
+/*************************************************
+* Zlib Compression Filter *
+*************************************************/
+class Zlib_Compression : public Filter
+ {
+ public:
+ void write(const byte input[], u32bit length);
+ void start_msg();
+ void end_msg();
+
+ void flush();
+
+ Zlib_Compression(u32bit = 6);
+ ~Zlib_Compression() { clear(); }
+ private:
+ void clear();
+ const u32bit level;
+ SecureVector<byte> buffer;
+ class Zlib_Stream* zlib;
+ };
+
+/*************************************************
+* Zlib Decompression Filter *
+*************************************************/
+class Zlib_Decompression : public Filter
+ {
+ public:
+ void write(const byte input[], u32bit length);
+ void start_msg();
+ void end_msg();
+
+ Zlib_Decompression();
+ ~Zlib_Decompression() { clear(); }
+ private:
+ void clear();
+ SecureVector<byte> buffer;
+ class Zlib_Stream* zlib;
+ bool no_writes;
+ };
+
+}
+
+#endif
diff --git a/modules/eng_aep/aep_conn.cpp b/modules/eng_aep/aep_conn.cpp
new file mode 100644
index 000000000..9293f45fc
--- /dev/null
+++ b/modules/eng_aep/aep_conn.cpp
@@ -0,0 +1,92 @@
+/*************************************************
+* AEP Connection Management Source File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#include <botan/aep_conn.h>
+#include <botan/libstate.h>
+#include <botan/parsing.h>
+#include <botan/hw_aep.h>
+
+namespace Botan {
+
+/*************************************************
+* Persistent connection pool *
+*************************************************/
+std::vector<AEP_Connection::Connection_Info> AEP_Connection::pool;
+Mutex* AEP_Connection::guard = 0;
+
+/*************************************************
+* Close all currently open connections *
+*************************************************/
+void AEP_Connection::close_all_connections()
+ {
+ guard->lock();
+ for(u32bit j = 0; j != pool.size(); j++)
+ AEP::AEP_CloseConnection(pool[j].id);
+ pool.clear();
+ guard->unlock();
+ delete guard;
+ guard = 0;
+ }
+
+/*************************************************
+* Get a new connection handle *
+*************************************************/
+AEP_Connection::AEP_Connection()
+ {
+ // FIXME: race condition
+ if(!guard)
+ guard = global_state().get_mutex();
+
+ Mutex_Holder lock(guard);
+
+ this_connection = 0;
+
+ for(u32bit j = 0; j != pool.size(); j++)
+ {
+ if(pool[j].in_use)
+ continue;
+
+ pool[j].in_use = true;
+ this_connection = pool[j].id;
+ }
+
+ if(this_connection == 0)
+ {
+ Connection_Info new_conn;
+
+ u32bit retval = AEP::AEP_OpenConnection(&new_conn.id);
+ if(retval != 0)
+ throw Stream_IO_Error("AEP_OpenConnection failed");
+ new_conn.in_use = true;
+
+ if(pool.size() < MAX_CACHED_CONNECTIONS)
+ pool.push_back(new_conn);
+
+ this_connection = new_conn.id;
+ }
+ }
+
+/*************************************************
+* Free a connection handle *
+*************************************************/
+AEP_Connection::~AEP_Connection()
+ {
+ Mutex_Holder lock(guard);
+
+ for(u32bit j = 0; j != pool.size(); j++)
+ {
+ if(pool[j].id != this_connection)
+ continue;
+
+ pool[j].in_use = false;
+ return;
+ }
+
+ int retval = AEP::AEP_CloseConnection(this_connection);
+ if(retval != 0)
+ throw Exception("AEP_CloseConnection returned " + to_string(retval));
+ }
+
+}
diff --git a/modules/eng_aep/aep_conn.h b/modules/eng_aep/aep_conn.h
new file mode 100644
index 000000000..18b8c76db
--- /dev/null
+++ b/modules/eng_aep/aep_conn.h
@@ -0,0 +1,38 @@
+/*************************************************
+* AEP Connection Management Header File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#ifndef BOTAN_EXT_AEP_CONNECTION_H__
+#define BOTAN_EXT_AEP_CONNECTION_H__
+
+#include <botan/eng_aep.h>
+#include <botan/mutex.h>
+
+namespace Botan {
+
+/*************************************************
+* AEP Connection *
+*************************************************/
+class AEP_Connection
+ {
+ public:
+ operator u32bit () { return this_connection; }
+
+ static void close_all_connections();
+
+ AEP_Connection();
+ ~AEP_Connection();
+ private:
+ struct Connection_Info { u32bit id; bool in_use; };
+
+ static const u32bit MAX_CACHED_CONNECTIONS = 8;
+ static std::vector<Connection_Info> pool;
+ static Mutex* guard;
+
+ u32bit this_connection;
+ };
+
+}
+
+#endif
diff --git a/modules/eng_aep/aep_main.cpp b/modules/eng_aep/aep_main.cpp
new file mode 100644
index 000000000..d941597da
--- /dev/null
+++ b/modules/eng_aep/aep_main.cpp
@@ -0,0 +1,191 @@
+/*************************************************
+* AEP Interface Source File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#include <botan/eng_aep.h>
+#include <botan/parsing.h>
+#include <botan/util.h>
+#include <botan/mutex.h>
+#include <botan/aep_conn.h>
+#include <botan/hw_aep.h>
+#include <botan/es_aep.h>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* AEP Exception *
+*************************************************/
+class AEP_Exception : public Exception
+ {
+ public:
+ AEP_Exception(const std::string func, u32bit retval) :
+ Exception(func + " failed; returned " + to_string(retval)) {}
+ };
+
+/*************************************************
+* Return the size in bytes of this BigInt *
+*************************************************/
+u32bit get_bigint_size(void* bigint_ptr, u32bit* bytes)
+ {
+ const BigInt* bigint = static_cast<BigInt*>(bigint_ptr);
+ const u32bit actual_bytes = bigint->bytes();
+ *bytes = round_up(actual_bytes, 4);
+ return 0;
+ }
+
+/*************************************************
+* Store a BigInt into AEP format *
+*************************************************/
+u32bit store_bigint(void* bigint_ptr, u32bit output_size, byte* output)
+ {
+ const BigInt* bigint = static_cast<BigInt*>(bigint_ptr);
+
+ const u32bit leading_zeros = round_up(bigint->bytes(), 4) - bigint->bytes();
+
+ clear_mem(output, output_size);
+ bigint->binary_encode(output + leading_zeros);
+ for(u32bit j = 0; j != output_size / 2; j++)
+ std::swap(output[j], output[output_size-j-1]);
+
+ return 0;
+ }
+
+/*************************************************
+* Read a BigInt from the AEP format *
+*************************************************/
+u32bit create_bigint(void* bigint_ptr, u32bit input_size, byte* input)
+ {
+ BigInt* bigint = static_cast<BigInt*>(bigint_ptr);
+
+ for(u32bit j = 0; j != input_size / 2; j++)
+ std::swap(input[j], input[input_size-j-1]);
+ bigint->binary_decode(input, input_size);
+
+ return 0;
+ }
+
+}
+
+/*************************************************
+* AEP Modular Exponentiation Operation *
+*************************************************/
+BigInt AEP_Engine::pow_mod(const BigInt& i, const BigInt& x, const BigInt& m)
+ {
+ BigInt output;
+
+ AEP_Connection conn;
+ u32bit retval = AEP::AEP_ModExp(conn, &i, &x, &m, &output, 0);
+
+ if(retval != 0)
+ throw AEP_Exception("AEP_ModExp", retval);
+
+ return output;
+ }
+
+/*************************************************
+* AEP Modular Exponentiation with CRT Operation *
+*************************************************/
+BigInt AEP_Engine::pow_mod_crt(const BigInt& i, const BigInt&,
+ const BigInt& p, const BigInt& q,
+ const BigInt& d1, const BigInt& d2,
+ const BigInt& c)
+ {
+ BigInt output;
+
+ AEP_Connection conn;
+ u32bit retval = AEP::AEP_ModExpCrt(conn, &i, &p, &q, &d1, &d2, &c,
+ &output, 0);
+
+ if(retval != 0)
+ throw AEP_Exception("AEP_ModExpCrt", retval);
+ return output;
+ }
+
+/*************************************************
+* AEP RNG Operation *
+*************************************************/
+u32bit AEP_Engine::get_entropy(byte output[], u32bit length) throw()
+ {
+ if(length > 256)
+ length = 256;
+
+ try {
+ AEP_Connection conn;
+ u32bit retval = AEP::AEP_GenRandom(conn, length, 1, output, 0);
+
+ if(retval != 0)
+ return 0;
+ return length;
+ }
+ catch(...)
+ {
+ return 0;
+ }
+ }
+
+/*************************************************
+* AEP usability check *
+*************************************************/
+bool AEP_Engine::ok_to_use(const BigInt& x) throw()
+ {
+ if(daemon_is_up && (x.bits() <= AEP::MAX_MODULO_BITS))
+ return true;
+ return false;
+ }
+
+/*************************************************
+* AEP daemon status flag *
+*************************************************/
+bool AEP_Engine::daemon_is_up = false;
+
+/*************************************************
+* AEP_Engine Constructor *
+*************************************************/
+AEP_Engine::AEP_Engine()
+ {
+ daemon_is_up = false;
+
+ try {
+ u32bit retval = AEP::AEP_Initialize(0);
+
+ if(retval != 0 && retval != AEP::ALREADY_INIT)
+ throw AEP_Exception("AEP_Initialize", retval);
+
+ if(retval == 0)
+ {
+ retval = AEP::AEP_SetBNCallBacks(get_bigint_size, store_bigint,
+ create_bigint);
+ if(retval != 0)
+ throw AEP_Exception("AEP_SetBNCallBacks", retval);
+
+ AEP_Connection conn;
+ daemon_is_up = true;
+ }
+
+ }
+ catch(AEP_Exception&) {}
+ }
+
+/*************************************************
+* AEP_Engine Destructor *
+*************************************************/
+AEP_Engine::~AEP_Engine()
+ {
+ AEP_Connection::close_all_connections();
+ u32bit retval = AEP::AEP_Finalize();
+ if(retval != 0)
+ throw AEP_Exception("AEP_Finalize", retval);
+ }
+
+/*************************************************
+* Gather Entropy from AEP Hardware RNG *
+*************************************************/
+u32bit AEP_EntropySource::slow_poll(byte output[], u32bit length)
+ {
+ return AEP_Engine::get_entropy(output, length);
+ }
+
+}
diff --git a/modules/eng_aep/eng_aep.cpp b/modules/eng_aep/eng_aep.cpp
new file mode 100644
index 000000000..557132b37
--- /dev/null
+++ b/modules/eng_aep/eng_aep.cpp
@@ -0,0 +1,352 @@
+/*************************************************
+* AEP Engine Source File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#include <botan/eng_aep.h>
+#include <botan/numthry.h>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* AEP IF Operation *
+*************************************************/
+class AEP_IF_Op : public IF_Operation
+ {
+ public:
+ BigInt public_op(const BigInt&) const;
+ BigInt private_op(const BigInt&) const;
+
+ IF_Operation* clone() const { return new AEP_IF_Op(*this); }
+
+ AEP_IF_Op(const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&);
+ private:
+ const BigInt e, n, p, q, d1, d2, c;
+ };
+
+/*************************************************
+* AEP_IF_Op Constructor *
+*************************************************/
+AEP_IF_Op::AEP_IF_Op(const BigInt& ex, const BigInt& nx, const BigInt&,
+ const BigInt& px, const BigInt& qx,
+ const BigInt& d1x, const BigInt& d2x,
+ const BigInt& cx) :
+ e(ex), n(nx), p(px), q(qx), d1(d1x), d2(d2x), c(cx)
+ {
+ }
+
+/*************************************************
+* AEP IF Public Operation *
+*************************************************/
+BigInt AEP_IF_Op::public_op(const BigInt& i) const
+ {
+ return AEP_Engine::pow_mod(i, e, n);
+ }
+
+/*************************************************
+* AEP IF Private Operation *
+*************************************************/
+BigInt AEP_IF_Op::private_op(const BigInt& i) const
+ {
+ if(p == 0 || q == 0)
+ throw Internal_Error("AEP_IF_Op::private_op: No private key");
+
+ return AEP_Engine::pow_mod_crt(i, n, p, q, d1, d2, c);
+ }
+
+/*************************************************
+* AEP DSA Operation *
+*************************************************/
+class AEP_DSA_Op : public DSA_Operation
+ {
+ public:
+ bool verify(const byte[], u32bit, const byte[], u32bit) const;
+ SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const;
+
+ DSA_Operation* clone() const { return new AEP_DSA_Op(*this); }
+
+ AEP_DSA_Op(const DL_Group&, const BigInt&, const BigInt&);
+ private:
+ const BigInt x, y;
+ const DL_Group group;
+ };
+
+/*************************************************
+* AEP_DSA_Op Constructor *
+*************************************************/
+AEP_DSA_Op::AEP_DSA_Op(const DL_Group& grp, const BigInt& y1,
+ const BigInt& x1) : x(x1), y(y1), group(grp)
+ {
+ }
+
+/*************************************************
+* AEP DSA Verify Operation *
+*************************************************/
+bool AEP_DSA_Op::verify(const byte msg[], u32bit msg_len,
+ const byte sig[], u32bit sig_len) const
+ {
+ const BigInt& g = group.get_g();
+ const BigInt& q = group.get_q();
+ const BigInt& p = group.get_p();
+
+ if(sig_len != 2*q.bytes() || msg_len > q.bytes())
+ return false;
+
+ BigInt r(sig, q.bytes());
+ BigInt s(sig + q.bytes(), q.bytes());
+ BigInt i(msg, msg_len);
+
+ if(r <= 0 || r >= q || s <= 0 || s >= q)
+ return false;
+
+ s = inverse_mod(s, q);
+ s = mul_mod(AEP_Engine::pow_mod(g, mul_mod(s, i, q), p),
+ AEP_Engine::pow_mod(y, mul_mod(s, r, q), p), p);
+
+ return (s % q == r);
+ }
+
+/*************************************************
+* AEP DSA Sign Operation *
+*************************************************/
+SecureVector<byte> AEP_DSA_Op::sign(const byte in[], u32bit length,
+ const BigInt& k) const
+ {
+ if(x == 0)
+ throw Internal_Error("AEP_DSA_Op::sign: No private key");
+
+ const BigInt& g = group.get_g();
+ const BigInt& q = group.get_q();
+ const BigInt& p = group.get_p();
+ BigInt i(in, length);
+
+ BigInt r = AEP_Engine::pow_mod(g, k, p) % q;
+ BigInt s = mul_mod(inverse_mod(k, q), mul_add(x, r, i), q);
+ if(r.is_zero() || s.is_zero())
+ throw Internal_Error("AEP_DSA_Op::sign: r or s was zero");
+
+ SecureVector<byte> output(2*q.bytes());
+ r.binary_encode(output + (output.size() / 2 - r.bytes()));
+ s.binary_encode(output + (output.size() - s.bytes()));
+ return output;
+ }
+
+/*************************************************
+* AEP NR Operation *
+*************************************************/
+class AEP_NR_Op : public NR_Operation
+ {
+ public:
+ SecureVector<byte> verify(const byte[], u32bit) const;
+ SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const;
+
+ NR_Operation* clone() const { return new AEP_NR_Op(*this); }
+
+ AEP_NR_Op(const DL_Group&, const BigInt&, const BigInt&);
+ private:
+ const BigInt x, y;
+ const DL_Group group;
+ };
+
+/*************************************************
+* AEP_NR_Op Constructor *
+*************************************************/
+AEP_NR_Op::AEP_NR_Op(const DL_Group& grp, const BigInt& y1,
+ const BigInt& x1) : x(x1), y(y1), group(grp)
+ {
+ }
+
+/*************************************************
+* AEP NR Verify Operation *
+*************************************************/
+SecureVector<byte> AEP_NR_Op::verify(const byte in[], u32bit length) const
+ {
+ const BigInt& g = group.get_g();
+ const BigInt& q = group.get_q();
+ const BigInt& p = group.get_p();
+
+ if(length != 2*q.bytes())
+ return false;
+
+ BigInt c(in, q.bytes());
+ BigInt d(in + q.bytes(), q.bytes());
+
+ if(c.is_zero() || c >= q || d >= q)
+ throw Invalid_Argument("AEP_NR_Op::verify: Invalid signature");
+
+ BigInt i = mul_mod(AEP_Engine::pow_mod(g, d, p),
+ AEP_Engine::pow_mod(y, c, p), p);
+ return BigInt::encode((c - i) % q);
+ }
+
+/*************************************************
+* AEP NR Sign Operation *
+*************************************************/
+SecureVector<byte> AEP_NR_Op::sign(const byte in[], u32bit length,
+ const BigInt& k) const
+ {
+ if(x == 0)
+ throw Internal_Error("AEP_NR_Op::sign: No private key");
+
+ const BigInt& g = group.get_g();
+ const BigInt& q = group.get_q();
+ const BigInt& p = group.get_p();
+
+ BigInt f(in, length);
+
+ if(f >= q)
+ throw Invalid_Argument("AEP_NR_Op::sign: Input is out of range");
+
+ BigInt c = (AEP_Engine::pow_mod(g, k, p) + f) % q;
+ if(c.is_zero())
+ throw Internal_Error("AEP_NR_Op::sign: c was zero");
+ BigInt d = (k - x * c) % q;
+
+ SecureVector<byte> output(2*q.bytes());
+ c.binary_encode(output + (output.size() / 2 - c.bytes()));
+ d.binary_encode(output + (output.size() - d.bytes()));
+ return output;
+ }
+
+/*************************************************
+* AEP ElGamal Operation *
+*************************************************/
+class AEP_ELG_Op : public ELG_Operation
+ {
+ public:
+ SecureVector<byte> encrypt(const byte[], u32bit, const BigInt&) const;
+ BigInt decrypt(const BigInt&, const BigInt&) const;
+
+ ELG_Operation* clone() const { return new AEP_ELG_Op(*this); }
+
+ AEP_ELG_Op(const DL_Group&, const BigInt&, const BigInt&);
+ private:
+ const BigInt x, y;
+ const DL_Group group;
+ };
+
+/*************************************************
+* AEP_ELG_Op Constructor *
+*************************************************/
+AEP_ELG_Op::AEP_ELG_Op(const DL_Group& grp, const BigInt& y1,
+ const BigInt& x1) : x(x1), y(y1), group(grp)
+ {
+ }
+
+/*************************************************
+* AEP ElGamal Encrypt Operation *
+*************************************************/
+SecureVector<byte> AEP_ELG_Op::encrypt(const byte in[], u32bit length,
+ const BigInt& k) const
+ {
+ const BigInt& g = group.get_g();
+ const BigInt& p = group.get_p();
+
+ BigInt m(in, length);
+ if(m >= p)
+ throw Invalid_Argument("AEP_ELG_Op::encrypt: Input is too large");
+
+ BigInt a = AEP_Engine::pow_mod(g, k, p);
+ BigInt b = mul_mod(m, AEP_Engine::pow_mod(y, k, p), p);
+
+ SecureVector<byte> output(2*p.bytes());
+ a.binary_encode(output + (p.bytes() - a.bytes()));
+ b.binary_encode(output + output.size() / 2 + (p.bytes() - b.bytes()));
+ return output;
+ }
+
+/*************************************************
+* AEP ElGamal Decrypt Operation *
+*************************************************/
+BigInt AEP_ELG_Op::decrypt(const BigInt& a, const BigInt& b) const
+ {
+ if(x == 0)
+ throw Internal_Error("AEP_ELG_Op::decrypt: No private key");
+
+ const BigInt& p = group.get_p();
+
+ if(a >= p || b >= p)
+ throw Invalid_Argument("AEP_ELG_Op: Invalid message");
+
+ return mul_mod(b, inverse_mod(AEP_Engine::pow_mod(a, x, p), p), p);
+ }
+
+/*************************************************
+* AEP DH Operation *
+*************************************************/
+class AEP_DH_Op : public DH_Operation
+ {
+ public:
+ BigInt agree(const BigInt& i) const
+ { return AEP_Engine::pow_mod(i, x, p); }
+ DH_Operation* clone() const { return new AEP_DH_Op(*this); }
+
+ AEP_DH_Op(const DL_Group& group, const BigInt& x1) :
+ x(x1), p(group.get_p()) {}
+ private:
+ const BigInt x, p;
+ };
+
+}
+
+/*************************************************
+* Acquire an IF op *
+*************************************************/
+IF_Operation* AEP_Engine::if_op(const BigInt& e, const BigInt& n,
+ const BigInt& d, const BigInt& p,
+ const BigInt& q, const BigInt& d1,
+ const BigInt& d2, const BigInt& c) const
+ {
+ if(AEP_Engine::ok_to_use(n))
+ return new AEP_IF_Op(e, n, d, p, q, d1, d2, c);
+ return 0;
+ }
+
+/*************************************************
+* Acquire a DSA op *
+*************************************************/
+DSA_Operation* AEP_Engine::dsa_op(const DL_Group& group, const BigInt& y,
+ const BigInt& x) const
+ {
+ if(AEP_Engine::ok_to_use(group.get_p()))
+ return new AEP_DSA_Op(group, y, x);
+ return 0;
+ }
+
+/*************************************************
+* Acquire a NR op *
+*************************************************/
+NR_Operation* AEP_Engine::nr_op(const DL_Group& group, const BigInt& y,
+ const BigInt& x) const
+ {
+ if(AEP_Engine::ok_to_use(group.get_p()))
+ return new AEP_NR_Op(group, y, x);
+ return 0;
+ }
+
+/*************************************************
+* Acquire an ElGamal op *
+*************************************************/
+ELG_Operation* AEP_Engine::elg_op(const DL_Group& group, const BigInt& y,
+ const BigInt& x) const
+ {
+ if(AEP_Engine::ok_to_use(group.get_p()))
+ return new AEP_ELG_Op(group, y, x);
+ return 0;
+ }
+
+/*************************************************
+* Acquire a DH op *
+*************************************************/
+DH_Operation* AEP_Engine::dh_op(const DL_Group& group, const BigInt& x) const
+ {
+ if(AEP_Engine::ok_to_use(group.get_p()))
+ return new AEP_DH_Op(group, x);
+ return 0;
+ }
+
+}
diff --git a/modules/eng_aep/eng_aep.h b/modules/eng_aep/eng_aep.h
new file mode 100644
index 000000000..0b47c7322
--- /dev/null
+++ b/modules/eng_aep/eng_aep.h
@@ -0,0 +1,51 @@
+/*************************************************
+* AEP Engine Header File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#ifndef BOTAN_EXT_AEP_ENGINE_H__
+#define BOTAN_EXT_AEP_ENGINE_H__
+
+#include <botan/engine.h>
+#include <vector>
+
+namespace Botan {
+
+/*************************************************
+* AEP Engine *
+*************************************************/
+class AEP_Engine : public Engine
+ {
+ public:
+ IF_Operation* if_op(const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&) const;
+
+ DSA_Operation* dsa_op(const DL_Group&, const BigInt&,
+ const BigInt&) const;
+
+ NR_Operation* nr_op(const DL_Group&, const BigInt&, const BigInt&) const;
+
+ ELG_Operation* elg_op(const DL_Group&, const BigInt&,
+ const BigInt&) const;
+
+ DH_Operation* dh_op(const DL_Group&, const BigInt&) const;
+
+ static BigInt pow_mod(const BigInt&, const BigInt&, const BigInt&);
+
+ static BigInt pow_mod_crt(const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&);
+
+ static u32bit get_entropy(byte[], u32bit) throw();
+ static bool ok_to_use(const BigInt&) throw();
+
+ AEP_Engine();
+ ~AEP_Engine();
+ private:
+ static bool daemon_is_up;
+ };
+
+}
+
+#endif
diff --git a/modules/eng_aep/es_aep.h b/modules/eng_aep/es_aep.h
new file mode 100644
index 000000000..bb58a9ef5
--- /dev/null
+++ b/modules/eng_aep/es_aep.h
@@ -0,0 +1,24 @@
+/*************************************************
+* AEP EntropySource Header File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#ifndef BOTAN_EXT_ENTROPY_SRC_AEP_H__
+#define BOTAN_EXT_ENTROPY_SRC_AEP_H__
+
+#include <botan/base.h>
+
+namespace Botan {
+
+/*************************************************
+* AEP Entropy Source *
+*************************************************/
+class AEP_EntropySource : public EntropySource
+ {
+ public:
+ u32bit slow_poll(byte[], u32bit);
+ };
+
+}
+
+#endif
diff --git a/modules/eng_aep/hw_aep.h b/modules/eng_aep/hw_aep.h
new file mode 100644
index 000000000..6e690e4a8
--- /dev/null
+++ b/modules/eng_aep/hw_aep.h
@@ -0,0 +1,48 @@
+/*************************************************
+* AEP Interface Header File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#ifndef BOTAN_EXT_HW_AEP_H__
+#define BOTAN_EXT_HW_AEP_H__
+
+#include <botan/types.h>
+
+namespace Botan {
+
+namespace AEP {
+
+const u32bit MAX_MODULO_BITS = 2048;
+
+const u32bit ALREADY_INIT = 0x10000191;
+
+extern "C" {
+
+u32bit AEP_Initialize(void*);
+u32bit AEP_Finalize();
+
+u32bit AEP_OpenConnection(u32bit*);
+u32bit AEP_CloseConnection(u32bit);
+
+u32bit AEP_ModExp(u32bit, const void*, const void*, const void*, void*,
+ u32bit*);
+u32bit AEP_ModExpCrt(u32bit, const void*, const void*, const void*,
+ const void*, const void*, const void*, void*,
+ u32bit*);
+
+u32bit AEP_GenRandom(u32bit, u32bit, u32bit, void*, u32bit*);
+
+typedef u32bit (*AEP_get_bignum_size_fn)(void*, u32bit*);
+typedef u32bit (*AEP_read_bignum_fn)(void*, u32bit, byte*);
+typedef u32bit (*AEP_write_bignum_fn)(void*, u32bit, byte*);
+
+u32bit AEP_SetBNCallBacks(AEP_get_bignum_size_fn, AEP_read_bignum_fn,
+ AEP_write_bignum_fn);
+
+}
+
+}
+
+}
+
+#endif
diff --git a/modules/eng_aep/modinfo.txt b/modules/eng_aep/modinfo.txt
new file mode 100644
index 000000000..b84790b97
--- /dev/null
+++ b/modules/eng_aep/modinfo.txt
@@ -0,0 +1,22 @@
+realname "AEP Engine"
+
+uses_external_libs
+
+add_file eng_aep.cpp
+add_file aep_main.cpp
+add_file aep_conn.cpp
+
+add_file eng_aep.h
+add_file es_aep.h
+add_file hw_aep.h
+add_file aep_conn.h
+
+local_only aep_conn.h
+local_only hw_aep.h
+
+define ENGINE_AEP
+define ENTROPY_SRC_AEP
+
+<libs>
+all -> aep
+</libs>
diff --git a/modules/eng_gmp/eng_gmp.cpp b/modules/eng_gmp/eng_gmp.cpp
new file mode 100644
index 000000000..944fa90f7
--- /dev/null
+++ b/modules/eng_gmp/eng_gmp.cpp
@@ -0,0 +1,377 @@
+/*************************************************
+* GMP Engine Source File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#include <botan/eng_gmp.h>
+#include <botan/gmp_wrap.h>
+#include <gmp.h>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* GMP IF Operation *
+*************************************************/
+class GMP_IF_Op : public IF_Operation
+ {
+ public:
+ BigInt public_op(const BigInt&) const;
+ BigInt private_op(const BigInt&) const;
+
+ IF_Operation* clone() const { return new GMP_IF_Op(*this); }
+
+ GMP_IF_Op(const BigInt& e_bn, const BigInt& n_bn, const BigInt&,
+ const BigInt& p_bn, const BigInt& q_bn, const BigInt& d1_bn,
+ const BigInt& d2_bn, const BigInt& c_bn) :
+ e(e_bn), n(n_bn), p(p_bn), q(q_bn), d1(d1_bn), d2(d2_bn), c(c_bn) {}
+ private:
+ const GMP_MPZ e, n, p, q, d1, d2, c;
+ };
+
+/*************************************************
+* GMP IF Public Operation *
+*************************************************/
+BigInt GMP_IF_Op::public_op(const BigInt& i_bn) const
+ {
+ GMP_MPZ i(i_bn);
+ mpz_powm(i.value, i.value, e.value, n.value);
+ return i.to_bigint();
+ }
+
+/*************************************************
+* GMP IF Private Operation *
+*************************************************/
+BigInt GMP_IF_Op::private_op(const BigInt& i_bn) const
+ {
+ if(mpz_cmp_ui(p.value, 0) == 0)
+ throw Internal_Error("GMP_IF_Op::private_op: No private key");
+
+ GMP_MPZ j1, j2, h(i_bn);
+
+ mpz_powm(j1.value, h.value, d1.value, p.value);
+ mpz_powm(j2.value, h.value, d2.value, q.value);
+ mpz_sub(h.value, j1.value, j2.value);
+ mpz_mul(h.value, h.value, c.value);
+ mpz_mod(h.value, h.value, p.value);
+ mpz_mul(h.value, h.value, q.value);
+ mpz_add(h.value, h.value, j2.value);
+ return h.to_bigint();
+ }
+
+/*************************************************
+* GMP DSA Operation *
+*************************************************/
+class GMP_DSA_Op : public DSA_Operation
+ {
+ public:
+ bool verify(const byte[], u32bit, const byte[], u32bit) const;
+ SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const;
+
+ DSA_Operation* clone() const { return new GMP_DSA_Op(*this); }
+
+ GMP_DSA_Op(const DL_Group& group, const BigInt& y1, const BigInt& x1) :
+ x(x1), y(y1), p(group.get_p()), q(group.get_q()), g(group.get_g()) {}
+ private:
+ const GMP_MPZ x, y, p, q, g;
+ };
+
+/*************************************************
+* GMP DSA Verify Operation *
+*************************************************/
+bool GMP_DSA_Op::verify(const byte msg[], u32bit msg_len,
+ const byte sig[], u32bit sig_len) const
+ {
+ const u32bit q_bytes = q.bytes();
+
+ if(sig_len != 2*q_bytes || msg_len > q_bytes)
+ return false;
+
+ GMP_MPZ r(sig, q_bytes);
+ GMP_MPZ s(sig + q_bytes, q_bytes);
+ GMP_MPZ i(msg, msg_len);
+
+ if(mpz_cmp_ui(r.value, 0) <= 0 || mpz_cmp(r.value, q.value) >= 0)
+ return false;
+ if(mpz_cmp_ui(s.value, 0) <= 0 || mpz_cmp(s.value, q.value) >= 0)
+ return false;
+
+ if(mpz_invert(s.value, s.value, q.value) == 0)
+ return false;
+
+ GMP_MPZ si;
+ mpz_mul(si.value, s.value, i.value);
+ mpz_mod(si.value, si.value, q.value);
+ mpz_powm(si.value, g.value, si.value, p.value);
+
+ GMP_MPZ sr;
+ mpz_mul(sr.value, s.value, r.value);
+ mpz_mod(sr.value, sr.value, q.value);
+ mpz_powm(sr.value, y.value, sr.value, p.value);
+
+ mpz_mul(si.value, si.value, sr.value);
+ mpz_mod(si.value, si.value, p.value);
+ mpz_mod(si.value, si.value, q.value);
+
+ if(mpz_cmp(si.value, r.value) == 0)
+ return true;
+ return false;
+ }
+
+/*************************************************
+* GMP DSA Sign Operation *
+*************************************************/
+SecureVector<byte> GMP_DSA_Op::sign(const byte in[], u32bit length,
+ const BigInt& k_bn) const
+ {
+ if(mpz_cmp_ui(x.value, 0) == 0)
+ throw Internal_Error("GMP_DSA_Op::sign: No private key");
+
+ GMP_MPZ i(in, length);
+ GMP_MPZ k(k_bn);
+
+ GMP_MPZ r;
+ mpz_powm(r.value, g.value, k.value, p.value);
+ mpz_mod(r.value, r.value, q.value);
+
+ mpz_invert(k.value, k.value, q.value);
+
+ GMP_MPZ s;
+ mpz_mul(s.value, x.value, r.value);
+ mpz_add(s.value, s.value, i.value);
+ mpz_mul(s.value, s.value, k.value);
+ mpz_mod(s.value, s.value, q.value);
+
+ if(mpz_cmp_ui(r.value, 0) == 0 || mpz_cmp_ui(s.value, 0) == 0)
+ throw Internal_Error("GMP_DSA_Op::sign: r or s was zero");
+
+ const u32bit q_bytes = q.bytes();
+
+ SecureVector<byte> output(2*q_bytes);
+ r.encode(output, q_bytes);
+ s.encode(output + q_bytes, q_bytes);
+ return output;
+ }
+
+/*************************************************
+* GMP NR Operation *
+*************************************************/
+class GMP_NR_Op : public NR_Operation
+ {
+ public:
+ SecureVector<byte> verify(const byte[], u32bit) const;
+ SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const;
+
+ NR_Operation* clone() const { return new GMP_NR_Op(*this); }
+
+ GMP_NR_Op(const DL_Group& group, const BigInt& y1, const BigInt& x1) :
+ x(x1), y(y1), p(group.get_p()), q(group.get_q()), g(group.get_g()) {}
+ private:
+ const GMP_MPZ x, y, p, q, g;
+ };
+
+/*************************************************
+* GMP NR Verify Operation *
+*************************************************/
+SecureVector<byte> GMP_NR_Op::verify(const byte sig[], u32bit sig_len) const
+ {
+ const u32bit q_bytes = q.bytes();
+
+ if(sig_len != 2*q_bytes)
+ return false;
+
+ GMP_MPZ c(sig, q_bytes);
+ GMP_MPZ d(sig + q_bytes, q_bytes);
+
+ if(mpz_cmp_ui(c.value, 0) <= 0 || mpz_cmp(c.value, q.value) >= 0 ||
+ mpz_cmp(d.value, q.value) >= 0)
+ throw Invalid_Argument("GMP_NR_Op::verify: Invalid signature");
+
+ GMP_MPZ i1, i2;
+ mpz_powm(i1.value, g.value, d.value, p.value);
+ mpz_powm(i2.value, y.value, c.value, p.value);
+ mpz_mul(i1.value, i1.value, i2.value);
+ mpz_mod(i1.value, i1.value, p.value);
+ mpz_sub(i1.value, c.value, i1.value);
+ mpz_mod(i1.value, i1.value, q.value);
+ return BigInt::encode(i1.to_bigint());
+ }
+
+/*************************************************
+* GMP NR Sign Operation *
+*************************************************/
+SecureVector<byte> GMP_NR_Op::sign(const byte in[], u32bit length,
+ const BigInt& k_bn) const
+ {
+ if(mpz_cmp_ui(x.value, 0) == 0)
+ throw Internal_Error("GMP_NR_Op::sign: No private key");
+
+ GMP_MPZ f(in, length);
+ GMP_MPZ k(k_bn);
+
+ if(mpz_cmp(f.value, q.value) >= 0)
+ throw Invalid_Argument("GMP_NR_Op::sign: Input is out of range");
+
+ GMP_MPZ c, d;
+ mpz_powm(c.value, g.value, k.value, p.value);
+ mpz_add(c.value, c.value, f.value);
+ mpz_mod(c.value, c.value, q.value);
+ mpz_mul(d.value, x.value, c.value);
+ mpz_sub(d.value, k.value, d.value);
+ mpz_mod(d.value, d.value, q.value);
+
+ if(mpz_cmp_ui(c.value, 0) == 0)
+ throw Internal_Error("Default_NR_Op::sign: c was zero");
+
+ const u32bit q_bytes = q.bytes();
+ SecureVector<byte> output(2*q_bytes);
+ c.encode(output, q_bytes);
+ d.encode(output + q_bytes, q_bytes);
+ return output;
+ }
+
+/*************************************************
+* GMP ElGamal Operation *
+*************************************************/
+class GMP_ELG_Op : public ELG_Operation
+ {
+ public:
+ SecureVector<byte> encrypt(const byte[], u32bit, const BigInt&) const;
+ BigInt decrypt(const BigInt&, const BigInt&) const;
+
+ ELG_Operation* clone() const { return new GMP_ELG_Op(*this); }
+
+ GMP_ELG_Op(const DL_Group& group, const BigInt& y1, const BigInt& x1) :
+ x(x1), y(y1), g(group.get_g()), p(group.get_p()) {}
+ private:
+ GMP_MPZ x, y, g, p;
+ };
+
+/*************************************************
+* GMP ElGamal Encrypt Operation *
+*************************************************/
+SecureVector<byte> GMP_ELG_Op::encrypt(const byte in[], u32bit length,
+ const BigInt& k_bn) const
+ {
+ GMP_MPZ i(in, length);
+
+ if(mpz_cmp(i.value, p.value) >= 0)
+ throw Invalid_Argument("GMP_ELG_Op: Input is too large");
+
+ GMP_MPZ a, b, k(k_bn);
+
+ mpz_powm(a.value, g.value, k.value, p.value);
+ mpz_powm(b.value, y.value, k.value, p.value);
+ mpz_mul(b.value, b.value, i.value);
+ mpz_mod(b.value, b.value, p.value);
+
+ const u32bit p_bytes = p.bytes();
+ SecureVector<byte> output(2*p_bytes);
+ a.encode(output, p_bytes);
+ b.encode(output + p_bytes, p_bytes);
+ return output;
+ }
+
+/*************************************************
+* GMP ElGamal Decrypt Operation *
+*************************************************/
+BigInt GMP_ELG_Op::decrypt(const BigInt& a_bn, const BigInt& b_bn) const
+ {
+ if(mpz_cmp_ui(x.value, 0) == 0)
+ throw Internal_Error("GMP_ELG_Op::decrypt: No private key");
+
+ GMP_MPZ a(a_bn), b(b_bn);
+
+ if(mpz_cmp(a.value, p.value) >= 0 || mpz_cmp(b.value, p.value) >= 0)
+ throw Invalid_Argument("GMP_ELG_Op: Invalid message");
+
+ mpz_powm(a.value, a.value, x.value, p.value);
+ mpz_invert(a.value, a.value, p.value);
+ mpz_mul(a.value, a.value, b.value);
+ mpz_mod(a.value, a.value, p.value);
+ return a.to_bigint();
+ }
+
+/*************************************************
+* GMP DH Operation *
+*************************************************/
+class GMP_DH_Op : public DH_Operation
+ {
+ public:
+ BigInt agree(const BigInt& i) const;
+ DH_Operation* clone() const { return new GMP_DH_Op(*this); }
+
+ GMP_DH_Op(const DL_Group& group, const BigInt& x_bn) :
+ x(x_bn), p(group.get_p()) {}
+ private:
+ GMP_MPZ x, p;
+ };
+
+/*************************************************
+* GMP DH Key Agreement Operation *
+*************************************************/
+BigInt GMP_DH_Op::agree(const BigInt& i_bn) const
+ {
+ GMP_MPZ i(i_bn);
+ mpz_powm(i.value, i.value, x.value, p.value);
+ return i.to_bigint();
+ }
+
+}
+
+/*************************************************
+* GMP_Engine Constructor *
+*************************************************/
+GMP_Engine::GMP_Engine()
+ {
+ set_memory_hooks();
+ }
+
+/*************************************************
+* Acquire an IF op *
+*************************************************/
+IF_Operation* GMP_Engine::if_op(const BigInt& e, const BigInt& n,
+ const BigInt& d, const BigInt& p,
+ const BigInt& q, const BigInt& d1,
+ const BigInt& d2, const BigInt& c) const
+ {
+ return new GMP_IF_Op(e, n, d, p, q, d1, d2, c);
+ }
+
+/*************************************************
+* Acquire a DSA op *
+*************************************************/
+DSA_Operation* GMP_Engine::dsa_op(const DL_Group& group, const BigInt& y,
+ const BigInt& x) const
+ {
+ return new GMP_DSA_Op(group, y, x);
+ }
+
+/*************************************************
+* Acquire a NR op *
+*************************************************/
+NR_Operation* GMP_Engine::nr_op(const DL_Group& group, const BigInt& y,
+ const BigInt& x) const
+ {
+ return new GMP_NR_Op(group, y, x);
+ }
+
+/*************************************************
+* Acquire an ElGamal op *
+*************************************************/
+ELG_Operation* GMP_Engine::elg_op(const DL_Group& group, const BigInt& y,
+ const BigInt& x) const
+ {
+ return new GMP_ELG_Op(group, y, x);
+ }
+
+/*************************************************
+* Acquire a DH op *
+*************************************************/
+DH_Operation* GMP_Engine::dh_op(const DL_Group& group, const BigInt& x) const
+ {
+ return new GMP_DH_Op(group, x);
+ }
+
+}
diff --git a/modules/eng_gmp/eng_gmp.h b/modules/eng_gmp/eng_gmp.h
new file mode 100644
index 000000000..08a66a3f8
--- /dev/null
+++ b/modules/eng_gmp/eng_gmp.h
@@ -0,0 +1,43 @@
+/*************************************************
+* GMP Engine Header File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#ifndef BOTAN_EXT_ENGINE_GMP_H__
+#define BOTAN_EXT_ENGINE_GMP_H__
+
+#include <botan/engine.h>
+
+namespace Botan {
+
+/*************************************************
+* GMP Engine *
+*************************************************/
+class GMP_Engine : public Engine
+ {
+ public:
+ IF_Operation* if_op(const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&) const;
+
+ DSA_Operation* dsa_op(const DL_Group&, const BigInt&,
+ const BigInt&) const;
+
+ NR_Operation* nr_op(const DL_Group&, const BigInt&, const BigInt&) const;
+
+ ELG_Operation* elg_op(const DL_Group&, const BigInt&,
+ const BigInt&) const;
+
+ DH_Operation* dh_op(const DL_Group&, const BigInt&) const;
+
+ Modular_Exponentiator* mod_exp(const BigInt&,
+ Power_Mod::Usage_Hints) const;
+
+ GMP_Engine();
+ private:
+ static void set_memory_hooks();
+ };
+
+}
+
+#endif
diff --git a/modules/eng_gmp/gmp_mem.cpp b/modules/eng_gmp/gmp_mem.cpp
new file mode 100644
index 000000000..1919c39e1
--- /dev/null
+++ b/modules/eng_gmp/gmp_mem.cpp
@@ -0,0 +1,60 @@
+/*************************************************
+* GNU MP Memory Handlers Source File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#include <botan/eng_gmp.h>
+#include <cstring>
+#include <gmp.h>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* Allocator used by GNU MP *
+*************************************************/
+Allocator* gmp_alloc = 0;
+
+/*************************************************
+* Allocation Function for GNU MP *
+*************************************************/
+void* gmp_malloc(size_t n)
+ {
+ return gmp_alloc->allocate(n);
+ }
+
+/*************************************************
+* Reallocation Function for GNU MP *
+*************************************************/
+void* gmp_realloc(void* ptr, size_t old_n, size_t new_n)
+ {
+ void* new_buf = gmp_alloc->allocate(new_n);
+ std::memcpy(new_buf, ptr, std::min(old_n, new_n));
+ gmp_alloc->deallocate(ptr, old_n);
+ return new_buf;
+ }
+
+/*************************************************
+* Deallocation Function for GNU MP *
+*************************************************/
+void gmp_free(void* ptr, size_t n)
+ {
+ gmp_alloc->deallocate(ptr, n);
+ }
+
+}
+
+/*************************************************
+* Set the GNU MP memory functions *
+*************************************************/
+void GMP_Engine::set_memory_hooks()
+ {
+ if(gmp_alloc == 0)
+ {
+ gmp_alloc = get_allocator();
+ mp_set_memory_functions(gmp_malloc, gmp_realloc, gmp_free);
+ }
+ }
+
+}
diff --git a/modules/eng_gmp/gmp_powm.cpp b/modules/eng_gmp/gmp_powm.cpp
new file mode 100644
index 000000000..c966a7b1c
--- /dev/null
+++ b/modules/eng_gmp/gmp_powm.cpp
@@ -0,0 +1,51 @@
+/*************************************************
+* GMP Modular Exponentiation Source File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#include <botan/eng_gmp.h>
+#include <botan/gmp_wrap.h>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* GMP Modular Exponentiator *
+*************************************************/
+class GMP_Modular_Exponentiator : public Modular_Exponentiator
+ {
+ public:
+ void set_base(const BigInt& b) { base = b; }
+ void set_exponent(const BigInt& e) { exp = e; }
+ BigInt execute() const;
+ Modular_Exponentiator* copy() const
+ { return new GMP_Modular_Exponentiator(*this); }
+
+ GMP_Modular_Exponentiator(const BigInt& n) : mod(n) {}
+ private:
+ GMP_MPZ base, exp, mod;
+ };
+
+/*************************************************
+* Compute the result *
+*************************************************/
+BigInt GMP_Modular_Exponentiator::execute() const
+ {
+ GMP_MPZ r;
+ mpz_powm(r.value, base.value, exp.value, mod.value);
+ return r.to_bigint();
+ }
+
+}
+
+/*************************************************
+* Return the GMP-based modular exponentiator *
+*************************************************/
+Modular_Exponentiator* GMP_Engine::mod_exp(const BigInt& n,
+ Power_Mod::Usage_Hints) const
+ {
+ return new GMP_Modular_Exponentiator(n);
+ }
+
+}
diff --git a/modules/eng_gmp/gmp_wrap.cpp b/modules/eng_gmp/gmp_wrap.cpp
new file mode 100644
index 000000000..b6b80560e
--- /dev/null
+++ b/modules/eng_gmp/gmp_wrap.cpp
@@ -0,0 +1,96 @@
+/*************************************************
+* GMP Wrapper Source File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#include <botan/gmp_wrap.h>
+
+#define GNU_MP_VERSION_CODE_FOR(a,b,c) ((a << 16) | (b << 8) | (c))
+
+#define GNU_MP_VERSION_CODE \
+ GNU_MP_VERSION_CODE_FOR(__GNU_MP_VERSION, __GNU_MP_VERSION_MINOR, \
+ __GNU_MP_VERSION_PATCHLEVEL)
+
+#if GNU_MP_VERSION_CODE < GNU_MP_VERSION_CODE_FOR(4,1,0)
+ #error Your GNU MP install is too old, upgrade to 4.1 or later
+#endif
+
+namespace Botan {
+
+/*************************************************
+* GMP_MPZ Constructor *
+*************************************************/
+GMP_MPZ::GMP_MPZ(const BigInt& in)
+ {
+ mpz_init(value);
+ if(in != 0)
+ mpz_import(value, in.sig_words(), -1, sizeof(word), 0, 0, in.data());
+ }
+
+/*************************************************
+* GMP_MPZ Constructor *
+*************************************************/
+GMP_MPZ::GMP_MPZ(const byte in[], u32bit length)
+ {
+ mpz_init(value);
+ mpz_import(value, length, 1, 1, 0, 0, in);
+ }
+
+/*************************************************
+* GMP_MPZ Copy Constructor *
+*************************************************/
+GMP_MPZ::GMP_MPZ(const GMP_MPZ& other)
+ {
+ mpz_init_set(value, other.value);
+ }
+
+/*************************************************
+* GMP_MPZ Destructor *
+*************************************************/
+GMP_MPZ::~GMP_MPZ()
+ {
+ mpz_clear(value);
+ }
+
+/*************************************************
+* GMP_MPZ Assignment Operator *
+*************************************************/
+GMP_MPZ& GMP_MPZ::operator=(const GMP_MPZ& other)
+ {
+ mpz_set(value, other.value);
+ return (*this);
+ }
+
+/*************************************************
+* Export the mpz_t as a bytestring *
+*************************************************/
+void GMP_MPZ::encode(byte out[], u32bit length) const
+ {
+ size_t dummy = 0;
+ mpz_export(out + (length - bytes()), &dummy, 1, 1, 0, 0, value);
+ }
+
+/*************************************************
+* Return the number of significant bytes *
+*************************************************/
+u32bit GMP_MPZ::bytes() const
+ {
+ return ((mpz_sizeinbase(value, 2) + 7) / 8);
+ }
+
+/*************************************************
+* GMP to BigInt Conversions *
+*************************************************/
+BigInt GMP_MPZ::to_bigint() const
+ {
+ BigInt out(BigInt::Positive, (bytes() + sizeof(word) - 1) / sizeof(word));
+ size_t dummy = 0;
+ mpz_export(out.get_reg(), &dummy, -1, sizeof(word), 0, 0, value);
+
+ if(mpz_sgn(value) < 0)
+ out.flip_sign();
+
+ return out;
+ }
+
+}
diff --git a/modules/eng_gmp/gmp_wrap.h b/modules/eng_gmp/gmp_wrap.h
new file mode 100644
index 000000000..34038d5f9
--- /dev/null
+++ b/modules/eng_gmp/gmp_wrap.h
@@ -0,0 +1,36 @@
+/*************************************************
+* GMP MPZ Wrapper Header File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#ifndef BOTAN_EXT_GMP_MPZ_WRAP_H__
+#define BOTAN_EXT_GMP_MPZ_WRAP_H__
+
+#include <botan/bigint.h>
+#include <gmp.h>
+
+namespace Botan {
+
+/*************************************************
+* Lightweight GMP mpz_t Wrapper *
+*************************************************/
+class GMP_MPZ
+ {
+ public:
+ mpz_t value;
+
+ BigInt to_bigint() const;
+ void encode(byte[], u32bit) const;
+ u32bit bytes() const;
+
+ GMP_MPZ& operator=(const GMP_MPZ&);
+
+ GMP_MPZ(const GMP_MPZ&);
+ GMP_MPZ(const BigInt& = 0);
+ GMP_MPZ(const byte[], u32bit);
+ ~GMP_MPZ();
+ };
+
+}
+
+#endif
diff --git a/modules/eng_gmp/modinfo.txt b/modules/eng_gmp/modinfo.txt
new file mode 100644
index 000000000..0e7d5465d
--- /dev/null
+++ b/modules/eng_gmp/modinfo.txt
@@ -0,0 +1,19 @@
+realname "GMP Engine"
+
+uses_external_libs
+
+add_file eng_gmp.cpp
+add_file gmp_wrap.cpp
+add_file gmp_mem.cpp
+add_file gmp_powm.cpp
+
+add_file eng_gmp.h
+add_file gmp_wrap.h
+
+local_only gmp_wrap.h
+
+define ENGINE_GNU_MP
+
+<libs>
+all -> gmp
+</libs>
diff --git a/modules/eng_ossl/bn_powm.cpp b/modules/eng_ossl/bn_powm.cpp
new file mode 100644
index 000000000..524379b72
--- /dev/null
+++ b/modules/eng_ossl/bn_powm.cpp
@@ -0,0 +1,52 @@
+/*************************************************
+* OpenSSL Modular Exponentiation Source File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#include <botan/eng_ossl.h>
+#include <botan/bn_wrap.h>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* OpenSSL Modular Exponentiator *
+*************************************************/
+class OpenSSL_Modular_Exponentiator : public Modular_Exponentiator
+ {
+ public:
+ void set_base(const BigInt& b) { base = b; }
+ void set_exponent(const BigInt& e) { exp = e; }
+ BigInt execute() const;
+ Modular_Exponentiator* copy() const
+ { return new OpenSSL_Modular_Exponentiator(*this); }
+
+ OpenSSL_Modular_Exponentiator(const BigInt& n) : mod(n) {}
+ private:
+ OSSL_BN base, exp, mod;
+ OSSL_BN_CTX ctx;
+ };
+
+/*************************************************
+* Compute the result *
+*************************************************/
+BigInt OpenSSL_Modular_Exponentiator::execute() const
+ {
+ OSSL_BN r;
+ BN_mod_exp(r.value, base.value, exp.value, mod.value, ctx.value);
+ return r.to_bigint();
+ }
+
+}
+
+/*************************************************
+* Return the OpenSSL-based modular exponentiator *
+*************************************************/
+Modular_Exponentiator* OpenSSL_Engine::mod_exp(const BigInt& n,
+ Power_Mod::Usage_Hints) const
+ {
+ return new OpenSSL_Modular_Exponentiator(n);
+ }
+
+}
diff --git a/modules/eng_ossl/bn_wrap.cpp b/modules/eng_ossl/bn_wrap.cpp
new file mode 100644
index 000000000..50c097724
--- /dev/null
+++ b/modules/eng_ossl/bn_wrap.cpp
@@ -0,0 +1,114 @@
+/*************************************************
+* OpenSSL BN Wrapper Source File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#include <botan/bn_wrap.h>
+
+namespace Botan {
+
+/*************************************************
+* OSSL_BN Constructor *
+*************************************************/
+OSSL_BN::OSSL_BN(const BigInt& in)
+ {
+ value = BN_new();
+ SecureVector<byte> encoding = BigInt::encode(in);
+ if(in != 0)
+ BN_bin2bn(encoding, encoding.size(), value);
+ }
+
+/*************************************************
+* OSSL_BN Constructor *
+*************************************************/
+OSSL_BN::OSSL_BN(const byte in[], u32bit length)
+ {
+ value = BN_new();
+ BN_bin2bn(in, length, value);
+ }
+
+/*************************************************
+* OSSL_BN Copy Constructor *
+*************************************************/
+OSSL_BN::OSSL_BN(const OSSL_BN& other)
+ {
+ value = BN_dup(other.value);
+ }
+
+/*************************************************
+* OSSL_BN Destructor *
+*************************************************/
+OSSL_BN::~OSSL_BN()
+ {
+ BN_clear_free(value);
+ }
+
+/*************************************************
+* OSSL_BN Assignment Operator *
+*************************************************/
+OSSL_BN& OSSL_BN::operator=(const OSSL_BN& other)
+ {
+ BN_copy(value, other.value);
+ return (*this);
+ }
+
+/*************************************************
+* Export the BIGNUM as a bytestring *
+*************************************************/
+void OSSL_BN::encode(byte out[], u32bit length) const
+ {
+ BN_bn2bin(value, out + (length - bytes()));
+ }
+
+/*************************************************
+* Return the number of significant bytes *
+*************************************************/
+u32bit OSSL_BN::bytes() const
+ {
+ return BN_num_bytes(value);
+ }
+
+/*************************************************
+* OpenSSL to BigInt Conversions *
+*************************************************/
+BigInt OSSL_BN::to_bigint() const
+ {
+ SecureVector<byte> out(bytes());
+ BN_bn2bin(value, out);
+ return BigInt::decode(out);
+ }
+
+/*************************************************
+* OSSL_BN_CTX Constructor *
+*************************************************/
+OSSL_BN_CTX::OSSL_BN_CTX()
+ {
+ value = BN_CTX_new();
+ }
+
+/*************************************************
+* OSSL_BN_CTX Copy Constructor *
+*************************************************/
+OSSL_BN_CTX::OSSL_BN_CTX(const OSSL_BN_CTX&)
+ {
+ value = BN_CTX_new();
+ }
+
+/*************************************************
+* OSSL_BN_CTX Destructor *
+*************************************************/
+OSSL_BN_CTX::~OSSL_BN_CTX()
+ {
+ BN_CTX_free(value);
+ }
+
+/*************************************************
+* OSSL_BN_CTX Assignment Operator *
+*************************************************/
+OSSL_BN_CTX& OSSL_BN_CTX::operator=(const OSSL_BN_CTX&)
+ {
+ value = BN_CTX_new();
+ return (*this);
+ }
+
+}
diff --git a/modules/eng_ossl/bn_wrap.h b/modules/eng_ossl/bn_wrap.h
new file mode 100644
index 000000000..2b90d643c
--- /dev/null
+++ b/modules/eng_ossl/bn_wrap.h
@@ -0,0 +1,51 @@
+/*************************************************
+* OpenSSL BN Wrapper Header File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#ifndef BOTAN_EXT_OPENSSL_BN_WRAP_H__
+#define BOTAN_EXT_OPENSSL_BN_WRAP_H__
+
+#include <botan/bigint.h>
+#include <openssl/bn.h>
+
+namespace Botan {
+
+/*************************************************
+* Lightweight OpenSSL BN Wrapper *
+*************************************************/
+class OSSL_BN
+ {
+ public:
+ BIGNUM* value;
+
+ BigInt to_bigint() const;
+ void encode(byte[], u32bit) const;
+ u32bit bytes() const;
+
+ OSSL_BN& operator=(const OSSL_BN&);
+
+ OSSL_BN(const OSSL_BN&);
+ OSSL_BN(const BigInt& = 0);
+ OSSL_BN(const byte[], u32bit);
+ ~OSSL_BN();
+ };
+
+/*************************************************
+* Lightweight OpenSSL BN_CTX Wrapper *
+*************************************************/
+class OSSL_BN_CTX
+ {
+ public:
+ BN_CTX* value;
+
+ OSSL_BN_CTX& operator=(const OSSL_BN_CTX&);
+
+ OSSL_BN_CTX();
+ OSSL_BN_CTX(const OSSL_BN_CTX&);
+ ~OSSL_BN_CTX();
+ };
+
+}
+
+#endif
diff --git a/modules/eng_ossl/eng_ossl.cpp b/modules/eng_ossl/eng_ossl.cpp
new file mode 100644
index 000000000..9c249876f
--- /dev/null
+++ b/modules/eng_ossl/eng_ossl.cpp
@@ -0,0 +1,374 @@
+/*************************************************
+* OpenSSL Engine Source File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#include <botan/eng_ossl.h>
+#include <botan/bn_wrap.h>
+#include <openssl/opensslv.h>
+
+#if OPENSSL_VERSION_NUMBER < 0x0090700F
+ #error Your OpenSSL install is too old, upgrade to 0.9.7 or later
+#endif
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* OpenSSL IF Operation *
+*************************************************/
+class OpenSSL_IF_Op : public IF_Operation
+ {
+ public:
+ BigInt public_op(const BigInt&) const;
+ BigInt private_op(const BigInt&) const;
+
+ IF_Operation* clone() const { return new OpenSSL_IF_Op(*this); }
+
+ OpenSSL_IF_Op(const BigInt& e_bn, const BigInt& n_bn, const BigInt&,
+ const BigInt& p_bn, const BigInt& q_bn, const BigInt& d1_bn,
+ const BigInt& d2_bn, const BigInt& c_bn) :
+ e(e_bn), n(n_bn), p(p_bn), q(q_bn), d1(d1_bn), d2(d2_bn), c(c_bn) {}
+ private:
+ const OSSL_BN e, n, p, q, d1, d2, c;
+ OSSL_BN_CTX ctx;
+ };
+
+/*************************************************
+* OpenSSL IF Public Operation *
+*************************************************/
+BigInt OpenSSL_IF_Op::public_op(const BigInt& i_bn) const
+ {
+ OSSL_BN i(i_bn), r;
+ BN_mod_exp(r.value, i.value, e.value, n.value, ctx.value);
+ return r.to_bigint();
+ }
+
+/*************************************************
+* OpenSSL IF Private Operation *
+*************************************************/
+BigInt OpenSSL_IF_Op::private_op(const BigInt& i_bn) const
+ {
+ if(BN_is_zero(p.value))
+ throw Internal_Error("OpenSSL_IF_Op::private_op: No private key");
+
+ OSSL_BN j1, j2, h(i_bn);
+
+ BN_mod_exp(j1.value, h.value, d1.value, p.value, ctx.value);
+ BN_mod_exp(j2.value, h.value, d2.value, q.value, ctx.value);
+ BN_sub(h.value, j1.value, j2.value);
+ BN_mod_mul(h.value, h.value, c.value, p.value, ctx.value);
+ BN_mul(h.value, h.value, q.value, ctx.value);
+ BN_add(h.value, h.value, j2.value);
+ return h.to_bigint();
+ }
+
+/*************************************************
+* OpenSSL DSA Operation *
+*************************************************/
+class OpenSSL_DSA_Op : public DSA_Operation
+ {
+ public:
+ bool verify(const byte[], u32bit, const byte[], u32bit) const;
+ SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const;
+
+ DSA_Operation* clone() const { return new OpenSSL_DSA_Op(*this); }
+
+ OpenSSL_DSA_Op(const DL_Group& group, const BigInt& y1,
+ const BigInt& x1) :
+ x(x1), y(y1), p(group.get_p()), q(group.get_q()), g(group.get_g()) {}
+ private:
+ const OSSL_BN x, y, p, q, g;
+ OSSL_BN_CTX ctx;
+ };
+
+/*************************************************
+* OpenSSL DSA Verify Operation *
+*************************************************/
+bool OpenSSL_DSA_Op::verify(const byte msg[], u32bit msg_len,
+ const byte sig[], u32bit sig_len) const
+ {
+ const u32bit q_bytes = q.bytes();
+
+ if(sig_len != 2*q_bytes || msg_len > q_bytes)
+ return false;
+
+ OSSL_BN r(sig, q_bytes);
+ OSSL_BN s(sig + q_bytes, q_bytes);
+ OSSL_BN i(msg, msg_len);
+
+ if(BN_is_zero(r.value) || BN_cmp(r.value, q.value) >= 0)
+ return false;
+ if(BN_is_zero(s.value) || BN_cmp(s.value, q.value) >= 0)
+ return false;
+
+ if(BN_mod_inverse(s.value, s.value, q.value, ctx.value) == 0)
+ return false;
+
+ OSSL_BN si;
+ BN_mod_mul(si.value, s.value, i.value, q.value, ctx.value);
+ BN_mod_exp(si.value, g.value, si.value, p.value, ctx.value);
+
+ OSSL_BN sr;
+ BN_mod_mul(sr.value, s.value, r.value, q.value, ctx.value);
+ BN_mod_exp(sr.value, y.value, sr.value, p.value, ctx.value);
+
+ BN_mod_mul(si.value, si.value, sr.value, p.value, ctx.value);
+ BN_nnmod(si.value, si.value, q.value, ctx.value);
+
+ if(BN_cmp(si.value, r.value) == 0)
+ return true;
+ return false;
+ }
+
+/*************************************************
+* OpenSSL DSA Sign Operation *
+*************************************************/
+SecureVector<byte> OpenSSL_DSA_Op::sign(const byte in[], u32bit length,
+ const BigInt& k_bn) const
+ {
+ if(BN_is_zero(x.value))
+ throw Internal_Error("OpenSSL_DSA_Op::sign: No private key");
+
+ OSSL_BN i(in, length);
+ OSSL_BN k(k_bn);
+
+ OSSL_BN r;
+ BN_mod_exp(r.value, g.value, k.value, p.value, ctx.value);
+ BN_nnmod(r.value, r.value, q.value, ctx.value);
+
+ BN_mod_inverse(k.value, k.value, q.value, ctx.value);
+
+ OSSL_BN s;
+ BN_mul(s.value, x.value, r.value, ctx.value);
+ BN_add(s.value, s.value, i.value);
+ BN_mod_mul(s.value, s.value, k.value, q.value, ctx.value);
+
+ if(BN_is_zero(r.value) || BN_is_zero(s.value))
+ throw Internal_Error("OpenSSL_DSA_Op::sign: r or s was zero");
+
+ const u32bit q_bytes = q.bytes();
+
+ SecureVector<byte> output(2*q_bytes);
+ r.encode(output, q_bytes);
+ s.encode(output + q_bytes, q_bytes);
+ return output;
+ }
+
+/*************************************************
+* OpenSSL NR Operation *
+*************************************************/
+class OpenSSL_NR_Op : public NR_Operation
+ {
+ public:
+ SecureVector<byte> verify(const byte[], u32bit) const;
+ SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const;
+
+ NR_Operation* clone() const { return new OpenSSL_NR_Op(*this); }
+
+ OpenSSL_NR_Op(const DL_Group& group, const BigInt& y1,
+ const BigInt& x1) :
+ x(x1), y(y1), p(group.get_p()), q(group.get_q()), g(group.get_g()) {}
+ private:
+ const OSSL_BN x, y, p, q, g;
+ OSSL_BN_CTX ctx;
+ };
+
+/*************************************************
+* OpenSSL NR Verify Operation *
+*************************************************/
+SecureVector<byte> OpenSSL_NR_Op::verify(const byte sig[],
+ u32bit sig_len) const
+ {
+ const u32bit q_bytes = q.bytes();
+
+ if(sig_len != 2*q_bytes)
+ return false;
+
+ OSSL_BN c(sig, q_bytes);
+ OSSL_BN d(sig + q_bytes, q_bytes);
+
+ if(BN_is_zero(c.value) || BN_cmp(c.value, q.value) >= 0 ||
+ BN_cmp(d.value, q.value) >= 0)
+ throw Invalid_Argument("OpenSSL_NR_Op::verify: Invalid signature");
+
+ OSSL_BN i1, i2;
+ BN_mod_exp(i1.value, g.value, d.value, p.value, ctx.value);
+ BN_mod_exp(i2.value, y.value, c.value, p.value, ctx.value);
+ BN_mod_mul(i1.value, i1.value, i2.value, p.value, ctx.value);
+ BN_sub(i1.value, c.value, i1.value);
+ BN_nnmod(i1.value, i1.value, q.value, ctx.value);
+ return BigInt::encode(i1.to_bigint());
+ }
+
+/*************************************************
+* OpenSSL NR Sign Operation *
+*************************************************/
+SecureVector<byte> OpenSSL_NR_Op::sign(const byte in[], u32bit length,
+ const BigInt& k_bn) const
+ {
+ if(BN_is_zero(x.value))
+ throw Internal_Error("OpenSSL_NR_Op::sign: No private key");
+
+ OSSL_BN f(in, length);
+ OSSL_BN k(k_bn);
+
+ if(BN_cmp(f.value, q.value) >= 0)
+ throw Invalid_Argument("OpenSSL_NR_Op::sign: Input is out of range");
+
+ OSSL_BN c, d;
+ BN_mod_exp(c.value, g.value, k.value, p.value, ctx.value);
+ BN_add(c.value, c.value, f.value);
+ BN_nnmod(c.value, c.value, q.value, ctx.value);
+ BN_mul(d.value, x.value, c.value, ctx.value);
+ BN_sub(d.value, k.value, d.value);
+ BN_nnmod(d.value, d.value, q.value, ctx.value);
+
+ if(BN_is_zero(c.value))
+ throw Internal_Error("Default_NR_Op::sign: c was zero");
+
+ const u32bit q_bytes = q.bytes();
+ SecureVector<byte> output(2*q_bytes);
+ c.encode(output, q_bytes);
+ d.encode(output + q_bytes, q_bytes);
+ return output;
+ }
+
+/*************************************************
+* OpenSSL ElGamal Operation *
+*************************************************/
+class OpenSSL_ELG_Op : public ELG_Operation
+ {
+ public:
+ SecureVector<byte> encrypt(const byte[], u32bit, const BigInt&) const;
+ BigInt decrypt(const BigInt&, const BigInt&) const;
+
+ ELG_Operation* clone() const { return new OpenSSL_ELG_Op(*this); }
+ OpenSSL_ELG_Op(const DL_Group& group, const BigInt& y1,
+ const BigInt& x1) :
+ x(x1), y(y1), g(group.get_g()), p(group.get_p()) {}
+ private:
+ OSSL_BN x, y, g, p;
+ OSSL_BN_CTX ctx;
+ };
+
+/*************************************************
+* OpenSSL ElGamal Encrypt Operation *
+*************************************************/
+SecureVector<byte> OpenSSL_ELG_Op::encrypt(const byte in[], u32bit length,
+ const BigInt& k_bn) const
+ {
+ OSSL_BN i(in, length);
+
+ if(BN_cmp(i.value, p.value) >= 0)
+ throw Invalid_Argument("OpenSSL_ELG_Op: Input is too large");
+
+ OSSL_BN a, b, k(k_bn);
+
+ BN_mod_exp(a.value, g.value, k.value, p.value, ctx.value);
+ BN_mod_exp(b.value, y.value, k.value, p.value, ctx.value);
+ BN_mod_mul(b.value, b.value, i.value, p.value, ctx.value);
+
+ const u32bit p_bytes = p.bytes();
+ SecureVector<byte> output(2*p_bytes);
+ a.encode(output, p_bytes);
+ b.encode(output + p_bytes, p_bytes);
+ return output;
+ }
+
+/*************************************************
+* OpenSSL ElGamal Decrypt Operation *
+*************************************************/
+BigInt OpenSSL_ELG_Op::decrypt(const BigInt& a_bn, const BigInt& b_bn) const
+ {
+ if(BN_is_zero(x.value))
+ throw Internal_Error("OpenSSL_ELG_Op::decrypt: No private key");
+
+ OSSL_BN a(a_bn), b(b_bn), t;
+
+ if(BN_cmp(a.value, p.value) >= 0 || BN_cmp(b.value, p.value) >= 0)
+ throw Invalid_Argument("OpenSSL_ELG_Op: Invalid message");
+
+ BN_mod_exp(t.value, a.value, x.value, p.value, ctx.value);
+ BN_mod_inverse(a.value, t.value, p.value, ctx.value);
+ BN_mod_mul(a.value, a.value, b.value, p.value, ctx.value);
+ return a.to_bigint();
+ }
+
+/*************************************************
+* OpenSSL DH Operation *
+*************************************************/
+class OpenSSL_DH_Op : public DH_Operation
+ {
+ public:
+ BigInt agree(const BigInt& i) const;
+ DH_Operation* clone() const { return new OpenSSL_DH_Op(*this); }
+
+ OpenSSL_DH_Op(const DL_Group& group, const BigInt& x_bn) :
+ x(x_bn), p(group.get_p()) {}
+ private:
+ OSSL_BN x, p;
+ OSSL_BN_CTX ctx;
+ };
+
+/*************************************************
+* OpenSSL DH Key Agreement Operation *
+*************************************************/
+BigInt OpenSSL_DH_Op::agree(const BigInt& i_bn) const
+ {
+ OSSL_BN i(i_bn), r;
+ BN_mod_exp(r.value, i.value, x.value, p.value, ctx.value);
+ return r.to_bigint();
+ }
+
+}
+
+/*************************************************
+* Acquire an IF op *
+*************************************************/
+IF_Operation* OpenSSL_Engine::if_op(const BigInt& e, const BigInt& n,
+ const BigInt& d, const BigInt& p,
+ const BigInt& q, const BigInt& d1,
+ const BigInt& d2, const BigInt& c) const
+ {
+ return new OpenSSL_IF_Op(e, n, d, p, q, d1, d2, c);
+ }
+
+/*************************************************
+* Acquire a DSA op *
+*************************************************/
+DSA_Operation* OpenSSL_Engine::dsa_op(const DL_Group& group, const BigInt& y,
+ const BigInt& x) const
+ {
+ return new OpenSSL_DSA_Op(group, y, x);
+ }
+
+/*************************************************
+* Acquire a NR op *
+*************************************************/
+NR_Operation* OpenSSL_Engine::nr_op(const DL_Group& group, const BigInt& y,
+ const BigInt& x) const
+ {
+ return new OpenSSL_NR_Op(group, y, x);
+ }
+
+/*************************************************
+* Acquire an ElGamal op *
+*************************************************/
+ELG_Operation* OpenSSL_Engine::elg_op(const DL_Group& group, const BigInt& y,
+ const BigInt& x) const
+ {
+ return new OpenSSL_ELG_Op(group, y, x);
+ }
+
+/*************************************************
+* Acquire a DH op *
+*************************************************/
+DH_Operation* OpenSSL_Engine::dh_op(const DL_Group& group,
+ const BigInt& x) const
+ {
+ return new OpenSSL_DH_Op(group, x);
+ }
+
+}
diff --git a/modules/eng_ossl/eng_ossl.h b/modules/eng_ossl/eng_ossl.h
new file mode 100644
index 000000000..e72b3ca43
--- /dev/null
+++ b/modules/eng_ossl/eng_ossl.h
@@ -0,0 +1,40 @@
+/*************************************************
+* OpenSSL Engine Header File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#ifndef BOTAN_EXT_ENGINE_OPENSSL_H__
+#define BOTAN_EXT_ENGINE_OPENSSL_H__
+
+#include <botan/engine.h>
+#include <botan/mutex.h>
+
+namespace Botan {
+
+/*************************************************
+* OpenSSL Engine *
+*************************************************/
+class OpenSSL_Engine : public Engine
+ {
+ public:
+ IF_Operation* if_op(const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&) const;
+ DSA_Operation* dsa_op(const DL_Group&, const BigInt&,
+ const BigInt&) const;
+ NR_Operation* nr_op(const DL_Group&, const BigInt&, const BigInt&) const;
+ ELG_Operation* elg_op(const DL_Group&, const BigInt&,
+ const BigInt&) const;
+ DH_Operation* dh_op(const DL_Group&, const BigInt&) const;
+
+ Modular_Exponentiator* mod_exp(const BigInt&,
+ Power_Mod::Usage_Hints) const;
+ private:
+ BlockCipher* find_block_cipher(const std::string&) const;
+ StreamCipher* find_stream_cipher(const std::string&) const;
+ HashFunction* find_hash(const std::string&) const;
+ };
+
+}
+
+#endif
diff --git a/modules/eng_ossl/modinfo.txt b/modules/eng_ossl/modinfo.txt
new file mode 100644
index 000000000..8d32bf247
--- /dev/null
+++ b/modules/eng_ossl/modinfo.txt
@@ -0,0 +1,21 @@
+realname "OpenSSL Engine"
+
+uses_external_libs
+
+add_file eng_ossl.cpp
+add_file bn_wrap.cpp
+add_file bn_powm.cpp
+add_file ossl_bc.cpp
+add_file ossl_rc4.cpp
+add_file ossl_md.cpp
+
+add_file eng_ossl.h
+add_file bn_wrap.h
+
+local_only bn_wrap.h
+
+define ENGINE_OPENSSL
+
+<libs>
+all -> crypto
+</libs>
diff --git a/modules/eng_ossl/ossl_bc.cpp b/modules/eng_ossl/ossl_bc.cpp
new file mode 100644
index 000000000..73b5f564a
--- /dev/null
+++ b/modules/eng_ossl/ossl_bc.cpp
@@ -0,0 +1,204 @@
+/*************************************************
+* OpenSSL Block Cipher Source File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#include <botan/eng_ossl.h>
+#include <botan/parsing.h>
+#include <botan/lookup.h>
+#include <openssl/evp.h>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* EVP Block Cipher *
+*************************************************/
+class EVP_BlockCipher : public BlockCipher
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return cipher_name; }
+ BlockCipher* clone() const;
+ EVP_BlockCipher(const EVP_CIPHER*, const std::string&);
+ EVP_BlockCipher(const EVP_CIPHER*, const std::string&,
+ u32bit, u32bit, u32bit);
+
+ ~EVP_BlockCipher();
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key(const byte[], u32bit);
+ std::string cipher_name;
+ mutable EVP_CIPHER_CTX encrypt, decrypt;
+ };
+
+/*************************************************
+* EVP Block Cipher Constructor *
+*************************************************/
+EVP_BlockCipher::EVP_BlockCipher(const EVP_CIPHER* algo,
+ const std::string& algo_name) :
+ BlockCipher(EVP_CIPHER_block_size(algo), EVP_CIPHER_key_length(algo)),
+ cipher_name(algo_name)
+ {
+ if(EVP_CIPHER_mode(algo) != EVP_CIPH_ECB_MODE)
+ throw Invalid_Argument("EVP_BlockCipher: Non-ECB EVP was passed in");
+
+ EVP_CIPHER_CTX_init(&encrypt);
+ EVP_CIPHER_CTX_init(&decrypt);
+
+ EVP_EncryptInit_ex(&encrypt, algo, 0, 0, 0);
+ EVP_DecryptInit_ex(&decrypt, algo, 0, 0, 0);
+
+ EVP_CIPHER_CTX_set_padding(&encrypt, 0);
+ EVP_CIPHER_CTX_set_padding(&decrypt, 0);
+ }
+
+/*************************************************
+* EVP Block Cipher Constructor *
+*************************************************/
+EVP_BlockCipher::EVP_BlockCipher(const EVP_CIPHER* algo,
+ const std::string& algo_name,
+ u32bit key_min, u32bit key_max,
+ u32bit key_mod) :
+ BlockCipher(EVP_CIPHER_block_size(algo), key_min, key_max, key_mod),
+ cipher_name(algo_name)
+ {
+ if(EVP_CIPHER_mode(algo) != EVP_CIPH_ECB_MODE)
+ throw Invalid_Argument("EVP_BlockCipher: Non-ECB EVP was passed in");
+
+ EVP_CIPHER_CTX_init(&encrypt);
+ EVP_CIPHER_CTX_init(&decrypt);
+
+ EVP_EncryptInit_ex(&encrypt, algo, 0, 0, 0);
+ EVP_DecryptInit_ex(&decrypt, algo, 0, 0, 0);
+
+ EVP_CIPHER_CTX_set_padding(&encrypt, 0);
+ EVP_CIPHER_CTX_set_padding(&decrypt, 0);
+ }
+
+/*************************************************
+* EVP Block Cipher Destructor *
+*************************************************/
+EVP_BlockCipher::~EVP_BlockCipher()
+ {
+ EVP_CIPHER_CTX_cleanup(&encrypt);
+ EVP_CIPHER_CTX_cleanup(&decrypt);
+ }
+
+/*************************************************
+* Encrypt a block *
+*************************************************/
+void EVP_BlockCipher::enc(const byte in[], byte out[]) const
+ {
+ int out_len = 0;
+ EVP_EncryptUpdate(&encrypt, out, &out_len, in, BLOCK_SIZE);
+ }
+
+/*************************************************
+* Decrypt a block *
+*************************************************/
+void EVP_BlockCipher::dec(const byte in[], byte out[]) const
+ {
+ int out_len = 0;
+ EVP_DecryptUpdate(&decrypt, out, &out_len, in, BLOCK_SIZE);
+ }
+
+/*************************************************
+* Set the key *
+*************************************************/
+void EVP_BlockCipher::key(const byte key[], u32bit length)
+ {
+ SecureVector<byte> full_key(key, length);
+
+ if(cipher_name == "TripleDES" && length == 16)
+ full_key.append(key, 8);
+ else
+ if(EVP_CIPHER_CTX_set_key_length(&encrypt, length) == 0 ||
+ EVP_CIPHER_CTX_set_key_length(&decrypt, length) == 0)
+ throw Invalid_Argument("EVP_BlockCipher: Bad key length for " +
+ cipher_name);
+
+ if(cipher_name == "RC2")
+ {
+ EVP_CIPHER_CTX_ctrl(&encrypt, EVP_CTRL_SET_RC2_KEY_BITS, length*8, 0);
+ EVP_CIPHER_CTX_ctrl(&decrypt, EVP_CTRL_SET_RC2_KEY_BITS, length*8, 0);
+ }
+
+ EVP_EncryptInit_ex(&encrypt, 0, 0, full_key.begin(), 0);
+ EVP_DecryptInit_ex(&decrypt, 0, 0, full_key.begin(), 0);
+ }
+
+/*************************************************
+* Return a clone of this object *
+*************************************************/
+BlockCipher* EVP_BlockCipher::clone() const
+ {
+ return new EVP_BlockCipher(EVP_CIPHER_CTX_cipher(&encrypt),
+ cipher_name, MINIMUM_KEYLENGTH,
+ MAXIMUM_KEYLENGTH, KEYLENGTH_MULTIPLE);
+ }
+
+/*************************************************
+* Clear memory of sensitive data *
+*************************************************/
+void EVP_BlockCipher::clear() throw()
+ {
+ const EVP_CIPHER* algo = EVP_CIPHER_CTX_cipher(&encrypt);
+
+ EVP_CIPHER_CTX_cleanup(&encrypt);
+ EVP_CIPHER_CTX_cleanup(&decrypt);
+ EVP_CIPHER_CTX_init(&encrypt);
+ EVP_CIPHER_CTX_init(&decrypt);
+ EVP_EncryptInit_ex(&encrypt, algo, 0, 0, 0);
+ EVP_DecryptInit_ex(&decrypt, algo, 0, 0, 0);
+ EVP_CIPHER_CTX_set_padding(&encrypt, 0);
+ EVP_CIPHER_CTX_set_padding(&decrypt, 0);
+ }
+
+}
+
+/*************************************************
+* Look for an algorithm with this name *
+*************************************************/
+BlockCipher*
+OpenSSL_Engine::find_block_cipher(const std::string& algo_spec) const
+ {
+#define HANDLE_EVP_CIPHER(NAME, EVP) \
+ if(algo_name == NAME) \
+ { \
+ if(name.size() == 1) \
+ return new EVP_BlockCipher(EVP, NAME); \
+ throw Invalid_Algorithm_Name(algo_spec); \
+ }
+
+#define HANDLE_EVP_CIPHER_KEYLEN(NAME, EVP, MIN, MAX, MOD) \
+ if(algo_name == NAME) \
+ { \
+ if(name.size() == 1) \
+ return new EVP_BlockCipher(EVP, NAME, MIN, MAX, MOD); \
+ throw Invalid_Algorithm_Name(algo_spec); \
+ }
+
+ std::vector<std::string> name = parse_algorithm_name(algo_spec);
+ if(name.size() == 0)
+ return 0;
+ const std::string algo_name = deref_alias(name[0]);
+
+ HANDLE_EVP_CIPHER_KEYLEN("Blowfish", EVP_bf_ecb(), 1, 56, 1);
+ HANDLE_EVP_CIPHER_KEYLEN("CAST-128", EVP_cast5_ecb(), 1, 16, 1);
+ HANDLE_EVP_CIPHER_KEYLEN("RC2", EVP_rc2_ecb(), 1, 32, 1);
+ HANDLE_EVP_CIPHER_KEYLEN("TripleDES", EVP_des_ede3_ecb(), 16, 24, 8);
+ HANDLE_EVP_CIPHER("DES", EVP_des_ecb());
+ HANDLE_EVP_CIPHER("AES-128", EVP_aes_128_ecb());
+ HANDLE_EVP_CIPHER("AES-192", EVP_aes_192_ecb());
+ HANDLE_EVP_CIPHER("AES-256", EVP_aes_256_ecb());
+
+#undef HANDLE_EVP_CIPHER
+#undef HANDLE_EVP_CIPHER_KEYLEN
+
+ return 0;
+ }
+
+}
diff --git a/modules/eng_ossl/ossl_md.cpp b/modules/eng_ossl/ossl_md.cpp
new file mode 100644
index 000000000..173c4efbe
--- /dev/null
+++ b/modules/eng_ossl/ossl_md.cpp
@@ -0,0 +1,121 @@
+/*************************************************
+* OpenSSL Hash Functions Source File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#include <botan/eng_ossl.h>
+#include <botan/parsing.h>
+#include <botan/lookup.h>
+#include <openssl/evp.h>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* EVP Hash Function *
+*************************************************/
+class EVP_HashFunction : public HashFunction
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return algo_name; }
+ HashFunction* clone() const;
+ EVP_HashFunction(const EVP_MD*, const std::string&);
+ ~EVP_HashFunction();
+ private:
+ void add_data(const byte[], u32bit);
+ void final_result(byte[]);
+
+ std::string algo_name;
+ EVP_MD_CTX md;
+ };
+
+/*************************************************
+* Update an EVP Hash Calculation *
+*************************************************/
+void EVP_HashFunction::add_data(const byte input[], u32bit length)
+ {
+ EVP_DigestUpdate(&md, input, length);
+ }
+
+/*************************************************
+* Finalize an EVP Hash Calculation *
+*************************************************/
+void EVP_HashFunction::final_result(byte output[])
+ {
+ EVP_DigestFinal_ex(&md, output, 0);
+ const EVP_MD* algo = EVP_MD_CTX_md(&md);
+ EVP_DigestInit_ex(&md, algo, 0);
+ }
+
+/*************************************************
+* Clear memory of sensitive data *
+*************************************************/
+void EVP_HashFunction::clear() throw()
+ {
+ const EVP_MD* algo = EVP_MD_CTX_md(&md);
+ EVP_DigestInit_ex(&md, algo, 0);
+ }
+
+/*************************************************
+* Return a clone of this object *
+*************************************************/
+HashFunction* EVP_HashFunction::clone() const
+ {
+ const EVP_MD* algo = EVP_MD_CTX_md(&md);
+ return new EVP_HashFunction(algo, name());
+ }
+
+/*************************************************
+* Create an EVP hash function *
+*************************************************/
+EVP_HashFunction::EVP_HashFunction(const EVP_MD* algo,
+ const std::string& name) :
+ HashFunction(EVP_MD_size(algo), EVP_MD_block_size(algo)),
+ algo_name(name)
+ {
+ EVP_MD_CTX_init(&md);
+ EVP_DigestInit_ex(&md, algo, 0);
+ }
+
+/*************************************************
+* Destroy an EVP hash function *
+*************************************************/
+EVP_HashFunction::~EVP_HashFunction()
+ {
+ EVP_MD_CTX_cleanup(&md);
+ }
+
+}
+
+/*************************************************
+* Look for an algorithm with this name *
+*************************************************/
+HashFunction* OpenSSL_Engine::find_hash(const std::string& algo_spec) const
+ {
+ std::vector<std::string> name = parse_algorithm_name(algo_spec);
+ if(name.size() == 0)
+ return 0;
+ const std::string algo_name = deref_alias(name[0]);
+
+#define HANDLE_EVP_MD(NAME, EVP) \
+ if(algo_name == NAME) \
+ { \
+ if(name.size() == 1) \
+ return new EVP_HashFunction(EVP, NAME); \
+ throw Invalid_Algorithm_Name(algo_spec); \
+ }
+
+ HANDLE_EVP_MD("SHA-160", EVP_sha1());
+ HANDLE_EVP_MD("MD2", EVP_md2());
+ HANDLE_EVP_MD("MD4", EVP_md4());
+ HANDLE_EVP_MD("MD5", EVP_md5());
+ HANDLE_EVP_MD("RIPEMD-160", EVP_ripemd160());
+
+#undef HANDLE_EVP_MD
+
+ return 0;
+ }
+
+}
diff --git a/modules/eng_ossl/ossl_rc4.cpp b/modules/eng_ossl/ossl_rc4.cpp
new file mode 100644
index 000000000..3c8f96f72
--- /dev/null
+++ b/modules/eng_ossl/ossl_rc4.cpp
@@ -0,0 +1,92 @@
+/*************************************************
+* OpenSSL ARC4 Source File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#include <botan/eng_ossl.h>
+#include <botan/lookup.h>
+#include <botan/parsing.h>
+#include <openssl/rc4.h>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* OpenSSL ARC4 *
+*************************************************/
+class OpenSSL_ARC4 : public StreamCipher
+ {
+ public:
+ void clear() throw() { std::memset(&state, 0, sizeof(state)); }
+ std::string name() const;
+ StreamCipher* clone() const { return new OpenSSL_ARC4(SKIP); }
+ OpenSSL_ARC4(u32bit s = 0) : StreamCipher(1, 32), SKIP(s) { clear(); }
+ ~OpenSSL_ARC4() { clear(); }
+ private:
+ void cipher(const byte[], byte[], u32bit);
+ void key(const byte[], u32bit);
+
+ const u32bit SKIP;
+ RC4_KEY state;
+ };
+
+/*************************************************
+* Return the name of this type *
+*************************************************/
+std::string OpenSSL_ARC4::name() const
+ {
+ if(SKIP == 0) return "ARC4";
+ if(SKIP == 256) return "MARK-4";
+ else return "RC4_skip(" + to_string(SKIP) + ")";
+ }
+
+/*************************************************
+* ARC4 Key Schedule *
+*************************************************/
+void OpenSSL_ARC4::key(const byte key[], u32bit length)
+ {
+ RC4_set_key(&state, length, key);
+ byte dummy = 0;
+ for(u32bit j = 0; j != SKIP; j++)
+ RC4(&state, 1, &dummy, &dummy);
+ }
+
+/*************************************************
+* ARC4 Encryption *
+*************************************************/
+void OpenSSL_ARC4::cipher(const byte in[], byte out[], u32bit length)
+ {
+ RC4(&state, length, in, out);
+ }
+
+}
+
+/*************************************************
+* Look for an algorithm with this name *
+*************************************************/
+StreamCipher*
+OpenSSL_Engine::find_stream_cipher(const std::string& algo_spec) const
+ {
+ std::vector<std::string> name = parse_algorithm_name(algo_spec);
+ if(name.size() == 0)
+ return 0;
+ const std::string algo_name = deref_alias(name[0]);
+
+#define HANDLE_TYPE_ONE_U32BIT(NAME, TYPE, DEFAULT) \
+ if(algo_name == NAME) \
+ { \
+ if(name.size() == 1) \
+ return new TYPE(DEFAULT); \
+ if(name.size() == 2) \
+ return new TYPE(to_u32bit(name[1])); \
+ throw Invalid_Algorithm_Name(algo_spec); \
+ }
+
+ HANDLE_TYPE_ONE_U32BIT("ARC4", OpenSSL_ARC4, 0);
+ HANDLE_TYPE_ONE_U32BIT("RC4_drop", OpenSSL_ARC4, 768);
+
+ return 0;
+ }
+
+}
diff --git a/modules/es_beos/es_beos.cpp b/modules/es_beos/es_beos.cpp
new file mode 100644
index 000000000..f1c575063
--- /dev/null
+++ b/modules/es_beos/es_beos.cpp
@@ -0,0 +1,65 @@
+/*************************************************
+* BeOS EntropySource Source File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#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/modules/es_beos/es_beos.h b/modules/es_beos/es_beos.h
new file mode 100644
index 000000000..591443256
--- /dev/null
+++ b/modules/es_beos/es_beos.h
@@ -0,0 +1,25 @@
+/*************************************************
+* BeOS EntropySource Header File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#ifndef BOTAN_EXT_ENTROPY_SRC_BEOS_H__
+#define BOTAN_EXT_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/modules/es_beos/modinfo.txt b/modules/es_beos/modinfo.txt
new file mode 100644
index 000000000..717978417
--- /dev/null
+++ b/modules/es_beos/modinfo.txt
@@ -0,0 +1,14 @@
+realname "BeOS Entropy Source"
+
+define ENTROPY_SRC_BEOS
+
+add_file es_beos.h
+add_file es_beos.cpp
+
+<os>
+beos
+</os>
+
+<libs>
+beos -> root,be
+</libs>
diff --git a/modules/es_capi/es_capi.cpp b/modules/es_capi/es_capi.cpp
new file mode 100644
index 000000000..95bc3d969
--- /dev/null
+++ b/modules/es_capi/es_capi.cpp
@@ -0,0 +1,109 @@
+/*************************************************
+* Win32 CryptoAPI EntropySource Source File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#include <botan/es_capi.h>
+#include <botan/parsing.h>
+#include <botan/conf.h>
+#include <windows.h>
+#include <wincrypt.h>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* CSP Handle *
+*************************************************/
+class CSP_Handle
+ {
+ public:
+ CSP_Handle(u64bit);
+ ~CSP_Handle();
+
+ void gen_random(byte[], u32bit) const;
+ bool is_valid() const { return valid; }
+
+ HCRYPTPROV get_handle() const { return handle; }
+ private:
+ HCRYPTPROV handle;
+ bool valid;
+ };
+
+/*************************************************
+* Call CryptGenRandom *
+*************************************************/
+void CSP_Handle::gen_random(byte out[], u32bit n) const
+ {
+ CryptGenRandom(handle, n, out);
+ }
+
+/*************************************************
+* Initialize a CSP Handle *
+*************************************************/
+CSP_Handle::CSP_Handle(u64bit capi_provider)
+ {
+ valid = false;
+ DWORD prov_type = (DWORD)capi_provider;
+
+ if(CryptAcquireContext(&handle, 0, 0, prov_type, CRYPT_VERIFYCONTEXT))
+ valid = true;
+ }
+
+/*************************************************
+* Destroy a CSP Handle *
+*************************************************/
+CSP_Handle::~CSP_Handle()
+ {
+ if(valid)
+ CryptReleaseContext(handle, 0);
+ }
+
+}
+
+/*************************************************
+* Gather Entropy from Win32 CAPI *
+*************************************************/
+u32bit Win32_CAPI_EntropySource::slow_poll(byte output[], u32bit length)
+ {
+ 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;
+
+ if(provs == "")
+ capi_provs = Config::get_list("rng/ms_capi_prov_type");
+ else
+ 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/modules/es_capi/es_capi.h b/modules/es_capi/es_capi.h
new file mode 100644
index 000000000..8025e9ce7
--- /dev/null
+++ b/modules/es_capi/es_capi.h
@@ -0,0 +1,28 @@
+/*************************************************
+* Win32 CAPI EntropySource Header File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#ifndef BOTAN_EXT_ENTROPY_SRC_WIN32_CAPI_H__
+#define BOTAN_EXT_ENTROPY_SRC_WIN32_CAPI_H__
+
+#include <botan/base.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/modules/es_capi/modinfo.txt b/modules/es_capi/modinfo.txt
new file mode 100644
index 000000000..a61e33834
--- /dev/null
+++ b/modules/es_capi/modinfo.txt
@@ -0,0 +1,17 @@
+realname "Win32 CryptoAPI Entropy Source"
+
+define ENTROPY_SRC_CAPI
+
+add_file es_capi.h
+add_file es_capi.cpp
+
+# 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/modules/es_egd/es_egd.cpp b/modules/es_egd/es_egd.cpp
new file mode 100644
index 000000000..cf46b15d2
--- /dev/null
+++ b/modules/es_egd/es_egd.cpp
@@ -0,0 +1,91 @@
+/*************************************************
+* EGD EntropySource Source File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#include <botan/es_egd.h>
+#include <botan/conf.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 {
+
+/*************************************************
+* EGD_EntropySource Constructor *
+*************************************************/
+EGD_EntropySource::EGD_EntropySource(const std::string& egd_paths)
+ {
+ std::vector<std::string> path_list = split_on(egd_paths, ':');
+ std::vector<std::string> defaults = Config::get_list("rng/egd_path");
+
+ for(u32bit j = 0; j != path_list.size(); j++)
+ paths.push_back(path_list[j]);
+ for(u32bit j = 0; j != defaults.size(); j++)
+ paths.push_back(defaults[j]);
+ }
+
+/*************************************************
+* 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, (struct sockaddr*)&addr, len))
+ { close(fd); return 0; }
+
+ byte buffer[2];
+ buffer[0] = 1;
+ buffer[1] = (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/modules/es_egd/es_egd.h b/modules/es_egd/es_egd.h
new file mode 100644
index 000000000..3af50ef35
--- /dev/null
+++ b/modules/es_egd/es_egd.h
@@ -0,0 +1,30 @@
+/*************************************************
+* EGD EntropySource Header File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#ifndef BOTAN_EXT_ENTROPY_SRC_EGD_H__
+#define BOTAN_EXT_ENTROPY_SRC_EGD_H__
+
+#include <botan/base.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::string& = "");
+ private:
+ u32bit do_poll(byte[], u32bit, const std::string&) const;
+ std::vector<std::string> paths;
+ };
+
+}
+
+#endif
diff --git a/modules/es_egd/modinfo.txt b/modules/es_egd/modinfo.txt
new file mode 100644
index 000000000..7ba68274d
--- /dev/null
+++ b/modules/es_egd/modinfo.txt
@@ -0,0 +1,26 @@
+realname "EGD Entropy Source"
+
+define ENTROPY_SRC_EGD
+
+add_file es_egd.h
+add_file es_egd.cpp
+
+<libs>
+solaris -> socket
+qnx -> socket
+</libs>
+
+<os>
+aix
+cygwin
+darwin
+freebsd
+hpux
+irix
+linux
+netbsd
+openbsd
+qnx
+solaris
+tru64
+</os>
diff --git a/modules/es_ftw/es_ftw.cpp b/modules/es_ftw/es_ftw.cpp
new file mode 100644
index 000000000..08a03c0e4
--- /dev/null
+++ b/modules/es_ftw/es_ftw.cpp
@@ -0,0 +1,110 @@
+/*************************************************
+* FTW EntropySource Source File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#include <botan/es_ftw.h>
+#include <botan/util.h>
+#include <fstream>
+#include <cstring>
+#include <vector>
+
+#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 {
+
+/*************************************************
+* FTW_EntropySource Constructor *
+*************************************************/
+FTW_EntropySource::FTW_EntropySource(const std::string& p) : path(p)
+ {
+ }
+
+/*************************************************
+* FTW Fast Poll *
+*************************************************/
+void FTW_EntropySource::do_fast_poll()
+ {
+ files_read = 0;
+ max_read = 32;
+ gather_from_dir(path);
+ }
+
+/*************************************************
+* FTW Slow Poll *
+*************************************************/
+void FTW_EntropySource::do_slow_poll()
+ {
+ files_read = 0;
+ max_read = 256;
+ gather_from_dir(path);
+ }
+
+/*************************************************
+* Gather Entropy From Directory Tree *
+*************************************************/
+void FTW_EntropySource::gather_from_dir(const std::string& dirname)
+ {
+ if(dirname == "" || files_read >= max_read)
+ return;
+
+ DIR* dir = opendir(dirname.c_str());
+ if(dir == 0)
+ return;
+
+ std::vector<std::string> subdirs;
+
+ dirent* entry = readdir(dir);
+ while(entry && (files_read < max_read))
+ {
+ if((std::strcmp(entry->d_name, ".") == 0) ||
+ (std::strcmp(entry->d_name, "..") == 0))
+ { entry = readdir(dir); continue; }
+
+ const std::string filename = dirname + '/' + entry->d_name;
+
+ struct stat stat_buf;
+ if(lstat(filename.c_str(), &stat_buf) == -1)
+ { entry = readdir(dir); continue; }
+
+ if(S_ISREG(stat_buf.st_mode))
+ gather_from_file(filename);
+ else if(S_ISDIR(stat_buf.st_mode))
+ subdirs.push_back(filename);
+ entry = readdir(dir);
+ }
+ closedir(dir);
+
+ for(u32bit j = 0; j != subdirs.size(); j++)
+ gather_from_dir(subdirs[j]);
+ }
+
+/*************************************************
+* Gather Entropy From A File *
+*************************************************/
+void FTW_EntropySource::gather_from_file(const std::string& filename)
+ {
+ int fd = ::open(filename.c_str(), O_RDONLY | O_NOCTTY);
+ if(fd == -1)
+ return;
+
+ SecureVector<byte> read_buf(1024);
+ ssize_t got = ::read(fd, (byte*)read_buf.begin(), read_buf.size());
+ close(fd);
+
+ if(got > 0)
+ {
+ add_bytes(read_buf, got);
+ files_read++;
+ }
+ }
+
+}
diff --git a/modules/es_ftw/es_ftw.h b/modules/es_ftw/es_ftw.h
new file mode 100644
index 000000000..7b450798b
--- /dev/null
+++ b/modules/es_ftw/es_ftw.h
@@ -0,0 +1,31 @@
+/*************************************************
+* File Tree Walking EntropySource Header File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#ifndef BOTAN_EXT_ENTROPY_SRC_FTW_H__
+#define BOTAN_EXT_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& = "/proc");
+ private:
+ void do_fast_poll();
+ void do_slow_poll();
+ void gather_from_dir(const std::string&);
+ void gather_from_file(const std::string&);
+ const std::string path;
+ u32bit files_read, max_read;
+ };
+
+}
+
+#endif
diff --git a/modules/es_ftw/modinfo.txt b/modules/es_ftw/modinfo.txt
new file mode 100644
index 000000000..d68ac7ac9
--- /dev/null
+++ b/modules/es_ftw/modinfo.txt
@@ -0,0 +1,24 @@
+realname "File Tree Walking Entropy Source"
+
+define ENTROPY_SRC_FTW
+
+add_file es_ftw.h
+add_file es_ftw.cpp
+
+<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/modules/es_unix/es_unix.cpp b/modules/es_unix/es_unix.cpp
new file mode 100644
index 000000000..d1efd4fa9
--- /dev/null
+++ b/modules/es_unix/es_unix.cpp
@@ -0,0 +1,105 @@
+/*************************************************
+* Unix EntropySource Source File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#include <botan/es_unix.h>
+#include <botan/unix_cmd.h>
+#include <botan/parsing.h>
+#include <botan/conf.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()
+ {
+ 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()
+ {
+ gather(2*1024);
+ }
+
+/*************************************************
+* Unix Slow Poll *
+*************************************************/
+void Unix_EntropySource::do_slow_poll()
+ {
+ gather(16*1024);
+ }
+
+/*************************************************
+* Gather Entropy From Several Unix_Programs *
+*************************************************/
+void Unix_EntropySource::gather(u32bit target_amount)
+ {
+ const u32bit MINIMAL_WORKING = 32;
+
+ u32bit got = 0;
+ for(u32bit j = 0; j != sources.size(); j++)
+ {
+ add_timestamp();
+
+ got += gather_from(sources[j]);
+ sources[j].working = (got >= MINIMAL_WORKING) ? true : false;
+
+ if(got >= target_amount)
+ break;
+ }
+ }
+
+/*************************************************
+* Gather entropy from a Unix program *
+*************************************************/
+u32bit Unix_EntropySource::gather_from(const Unix_Program& prog)
+ {
+ const std::string BASE_PATH = "/bin:/sbin:/usr/bin:/usr/sbin";
+ const std::string EXTRA_PATH = Config::get_string("rng/unix_path");
+
+ std::string PATH = BASE_PATH;
+ if(EXTRA_PATH != "")
+ PATH += ':' + EXTRA_PATH;
+
+ DataSource_Command pipe(prog.name_and_args, PATH);
+ if(pipe.end_of_data())
+ return 0;
+
+ u32bit got = 0;
+ SecureVector<byte> buffer(DEFAULT_BUFFERSIZE);
+
+ while(!pipe.end_of_data())
+ {
+ u32bit this_loop = pipe.read(buffer, buffer.size());
+ add_bytes(buffer, this_loop);
+ got += this_loop;
+ }
+
+ return got;
+ }
+
+}
diff --git a/modules/es_unix/es_unix.h b/modules/es_unix/es_unix.h
new file mode 100644
index 000000000..74f960eb8
--- /dev/null
+++ b/modules/es_unix/es_unix.h
@@ -0,0 +1,35 @@
+/*************************************************
+* Unix EntropySource Header File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#ifndef BOTAN_EXT_ENTROPY_SRC_UNIX_H__
+#define BOTAN_EXT_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();
+ private:
+ void do_fast_poll();
+ void do_slow_poll();
+ void gather(u32bit);
+ u32bit gather_from(const Unix_Program&);
+ static void add_default_sources(std::vector<Unix_Program>&);
+
+ std::vector<Unix_Program> sources;
+ };
+
+}
+
+#endif
diff --git a/modules/es_unix/modinfo.txt b/modules/es_unix/modinfo.txt
new file mode 100644
index 000000000..94d922c05
--- /dev/null
+++ b/modules/es_unix/modinfo.txt
@@ -0,0 +1,25 @@
+realname "Generic Unix Entropy Source"
+
+define ENTROPY_SRC_UNIX
+
+add_file es_unix.cpp
+add_file unix_src.cpp
+add_file unix_cmd.cpp
+
+add_file es_unix.h
+add_file unix_cmd.h
+
+<os>
+aix
+beos
+cygwin
+darwin
+freebsd
+hpux
+irix
+linux
+netbsd
+qnx
+solaris
+tru64
+</os>
diff --git a/modules/es_unix/unix_cmd.cpp b/modules/es_unix/unix_cmd.cpp
new file mode 100644
index 000000000..db79478df
--- /dev/null
+++ b/modules/es_unix/unix_cmd.cpp
@@ -0,0 +1,241 @@
+/*************************************************
+* Unix Command Execution Source File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#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 <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, 0);
+ }
+ }
+
+}
+
+/*************************************************
+* 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 (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::string& path)
+ {
+ const std::vector<std::string> paths = split_on(path, ':');
+
+ 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::string& path) :
+ 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(path);
+ }
+
+/*************************************************
+* DataSource_Command Destructor *
+*************************************************/
+DataSource_Command::~DataSource_Command()
+ {
+ if(!end_of_data())
+ shutdown_pipe();
+ }
+
+}
diff --git a/modules/es_unix/unix_cmd.h b/modules/es_unix/unix_cmd.h
new file mode 100644
index 000000000..8da81ccbd
--- /dev/null
+++ b/modules/es_unix/unix_cmd.h
@@ -0,0 +1,56 @@
+/*************************************************
+* Unix Command Execution Header File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#ifndef BOTAN_EXT_UNIX_CMD_H__
+#define BOTAN_EXT_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::string&);
+ ~DataSource_Command();
+ private:
+ void create_pipe(const 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/modules/es_unix/unix_src.cpp b/modules/es_unix/unix_src.cpp
new file mode 100644
index 000000000..5493d9fd8
--- /dev/null
+++ b/modules/es_unix/unix_src.cpp
@@ -0,0 +1,59 @@
+/*************************************************
+* Program List for Unix_EntropySource *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#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/modules/es_win32/es_win32.cpp b/modules/es_win32/es_win32.cpp
new file mode 100644
index 000000000..fda02effe
--- /dev/null
+++ b/modules/es_win32/es_win32.cpp
@@ -0,0 +1,105 @@
+/*************************************************
+* Win32 EntropySource Source File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#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));
+ }
+
+}
diff --git a/modules/es_win32/es_win32.h b/modules/es_win32/es_win32.h
new file mode 100644
index 000000000..7ca9f1285
--- /dev/null
+++ b/modules/es_win32/es_win32.h
@@ -0,0 +1,25 @@
+/*************************************************
+* Win32 EntropySource Header File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#ifndef BOTAN_EXT_ENTROPY_SRC_WIN32_H__
+#define BOTAN_EXT_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/modules/es_win32/modinfo.txt b/modules/es_win32/modinfo.txt
new file mode 100644
index 000000000..67e1a6ec0
--- /dev/null
+++ b/modules/es_win32/modinfo.txt
@@ -0,0 +1,18 @@
+realname "MS Windows Entropy Source"
+
+# Probably not much of an issue anymore
+#note "This module will not run under NT4"
+
+define ENTROPY_SRC_WIN32
+
+add_file es_win32.h
+add_file es_win32.cpp
+
+<os>
+windows
+cygwin
+</os>
+
+<libs>
+windows -> user32
+</libs>
diff --git a/modules/fd_unix/fd_unix.cpp b/modules/fd_unix/fd_unix.cpp
new file mode 100644
index 000000000..8b7b2648a
--- /dev/null
+++ b/modules/fd_unix/fd_unix.cpp
@@ -0,0 +1,50 @@
+/*************************************************
+* Pipe I/O for Unix Source File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#include <botan/pipe.h>
+#include <unistd.h>
+
+namespace Botan {
+
+/*************************************************
+* Write data from a pipe into a Unix fd *
+*************************************************/
+int operator<<(int fd, Pipe& pipe)
+ {
+ SecureVector<byte> buffer(DEFAULT_BUFFERSIZE);
+ while(pipe.remaining())
+ {
+ u32bit got = pipe.read(buffer, buffer.size());
+ u32bit position = 0;
+ while(got)
+ {
+ ssize_t ret = write(fd, buffer + position, got);
+ if(ret == -1)
+ throw Stream_IO_Error("Pipe output operator (unixfd) has failed");
+ position += ret;
+ got -= ret;
+ }
+ }
+ return fd;
+ }
+
+/*************************************************
+* Read data from a Unix fd into a pipe *
+*************************************************/
+int operator>>(int fd, Pipe& pipe)
+ {
+ SecureVector<byte> buffer(DEFAULT_BUFFERSIZE);
+ while(true)
+ {
+ ssize_t ret = read(fd, buffer, buffer.size());
+ if(ret == 0) break;
+ if(ret == -1)
+ throw Stream_IO_Error("Pipe input operator (unixfd) has failed");
+ pipe.write(buffer, ret);
+ }
+ return fd;
+ }
+
+}
diff --git a/modules/fd_unix/fd_unix.h b/modules/fd_unix/fd_unix.h
new file mode 100644
index 000000000..f00cb8020
--- /dev/null
+++ b/modules/fd_unix/fd_unix.h
@@ -0,0 +1,21 @@
+/*************************************************
+* Pipe I/O for Unix Header File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#ifndef BOTAN_EXT_PIPE_UNIXFD_H__
+#define BOTAN_EXT_PIPE_UNIXFD_H__
+
+#include <botan/pipe.h>
+
+namespace Botan {
+
+/*************************************************
+* Unix I/O Operators for Pipe *
+*************************************************/
+int operator<<(int, Pipe&);
+int operator>>(int, Pipe&);
+
+}
+
+#endif
diff --git a/modules/fd_unix/modinfo.txt b/modules/fd_unix/modinfo.txt
new file mode 100644
index 000000000..062b93cca
--- /dev/null
+++ b/modules/fd_unix/modinfo.txt
@@ -0,0 +1,22 @@
+realname "Pipe Unix I/O support"
+
+define PIPE_UNIXFD_IO
+
+add_file fd_unix.h
+add_file fd_unix.cpp
+
+<os>
+aix
+beos
+cygwin
+darwin
+freebsd
+hpux
+irix
+linux
+netbsd
+openbsd
+qnx
+solaris
+tru64
+</os>
diff --git a/modules/ml_unix/mlock.cpp b/modules/ml_unix/mlock.cpp
new file mode 100644
index 000000000..937308739
--- /dev/null
+++ b/modules/ml_unix/mlock.cpp
@@ -0,0 +1,33 @@
+/*************************************************
+* Memory Locking Functions Source File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#include <botan/util.h>
+
+#ifndef _POSIX_C_SOURCE
+ #define _POSIX_C_SOURCE 199309
+#endif
+
+#include <sys/types.h>
+#include <sys/mman.h>
+
+namespace Botan {
+
+/*************************************************
+* Lock an area of memory into RAM *
+*************************************************/
+void lock_mem(void* ptr, u32bit bytes)
+ {
+ mlock(ptr, bytes);
+ }
+
+/*************************************************
+* Unlock a previously locked region of memory *
+*************************************************/
+void unlock_mem(void* ptr, u32bit bytes)
+ {
+ munlock(ptr, bytes);
+ }
+
+}
diff --git a/modules/ml_unix/modinfo.txt b/modules/ml_unix/modinfo.txt
new file mode 100644
index 000000000..bc05f0d08
--- /dev/null
+++ b/modules/ml_unix/modinfo.txt
@@ -0,0 +1,21 @@
+realname "Memory Locking for Unix"
+
+replace_file mlock.cpp
+
+<os>
+aix
+darwin
+freebsd
+hpux
+irix
+linux
+netbsd
+openbsd
+qnx
+solaris
+tru64
+</os>
+
+<libs>
+tru64 -> rt
+</libs>
diff --git a/modules/ml_win32/mlock.cpp b/modules/ml_win32/mlock.cpp
new file mode 100644
index 000000000..7384beb07
--- /dev/null
+++ b/modules/ml_win32/mlock.cpp
@@ -0,0 +1,27 @@
+/*************************************************
+* Memory Locking Functions Source File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#include <botan/util.h>
+#include <windows.h>
+
+namespace Botan {
+
+/*************************************************
+* Lock an area of memory into RAM *
+*************************************************/
+void lock_mem(void* ptr, u32bit bytes)
+ {
+ VirtualLock(ptr, bytes);
+ }
+
+/*************************************************
+* Unlock a previously locked region of memory *
+*************************************************/
+void unlock_mem(void* ptr, u32bit bytes)
+ {
+ VirtualUnlock(ptr, bytes);
+ }
+
+}
diff --git a/modules/ml_win32/modinfo.txt b/modules/ml_win32/modinfo.txt
new file mode 100644
index 000000000..31b5d2afa
--- /dev/null
+++ b/modules/ml_win32/modinfo.txt
@@ -0,0 +1,8 @@
+realname "Memory Locking for Windows"
+
+replace_file mlock.cpp
+
+<os>
+windows
+cygwin
+</os>
diff --git a/modules/mod_qt/modinfo.txt b/modules/mod_qt/modinfo.txt
new file mode 100644
index 000000000..ee91ef735
--- /dev/null
+++ b/modules/mod_qt/modinfo.txt
@@ -0,0 +1,19 @@
+realname "Support for Qt/QCA"
+
+define MUTEX_QT
+
+note "You'll probably have to add -I/-L flags to the Makefile to find Qt"
+
+replace_file types.h
+
+uses_external_libs
+
+replace_file types.h
+add_file mux_qt.cpp
+add_file mux_qt.h
+
+# I think we want to always use qt-mt, not qt -- not much point in supporting
+# mutexes in a single threaded application, after all.
+<libs>
+all -> qt-mt
+</libs>
diff --git a/modules/mod_qt/mux_qt.cpp b/modules/mod_qt/mux_qt.cpp
new file mode 100644
index 000000000..0d419d38a
--- /dev/null
+++ b/modules/mod_qt/mux_qt.cpp
@@ -0,0 +1,56 @@
+/*************************************************
+* Qt Thread Mutex Source File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#include <botan/mux_qt.h>
+#include <botan/exceptn.h>
+#include <qmutex.h>
+
+#if !defined(QT_THREAD_SUPPORT)
+ #error Your version of Qt does not support threads or mutexes
+#endif
+
+namespace Botan {
+
+/*************************************************
+* Wrapper Type for Qt Thread Mutex *
+*************************************************/
+struct mutex_wrapper
+ {
+ QMutex m;
+ };
+
+/*************************************************
+* Constructor *
+*************************************************/
+Qt_Mutex::Qt_Mutex()
+ {
+ mutex = new mutex_wrapper;
+ }
+
+/*************************************************
+* Destructor *
+*************************************************/
+Qt_Mutex::~Qt_Mutex()
+ {
+ delete mutex;
+ }
+
+/*************************************************
+* Lock the Mutex *
+*************************************************/
+void Qt_Mutex::lock()
+ {
+ mutex->m.lock();
+ }
+
+/*************************************************
+* Unlock the Mutex *
+*************************************************/
+void Qt_Mutex::unlock()
+ {
+ mutex->m.unlock();
+ }
+
+}
diff --git a/modules/mod_qt/mux_qt.h b/modules/mod_qt/mux_qt.h
new file mode 100644
index 000000000..1535b3d36
--- /dev/null
+++ b/modules/mod_qt/mux_qt.h
@@ -0,0 +1,31 @@
+/*************************************************
+* Qt Thread Mutex Header File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#ifndef BOTAN_EXT_MUTEX_QT_H__
+#define BOTAN_EXT_MUTEX_QT_H__
+
+#include <botan/mutex.h>
+
+namespace Botan {
+
+/*************************************************
+* Qt Mutex *
+*************************************************/
+class Qt_Mutex : public Mutex
+ {
+ public:
+ void lock();
+ void unlock();
+ Mutex* clone() const { return new Qt_Mutex; }
+
+ Qt_Mutex();
+ ~Qt_Mutex();
+ private:
+ struct mutex_wrapper* mutex;
+ };
+
+}
+
+#endif
diff --git a/modules/mod_qt/types.h b/modules/mod_qt/types.h
new file mode 100644
index 000000000..9f1b40666
--- /dev/null
+++ b/modules/mod_qt/types.h
@@ -0,0 +1,28 @@
+/*************************************************
+* Low Level Types Header File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#ifndef BOTAN_TYPES_H__
+#define BOTAN_TYPES_H__
+
+#include <qglobal.h>
+
+namespace Botan {
+
+typedef Q_UINT8 byte;
+typedef Q_UINT16 u16bit;
+typedef Q_UINT32 u32bit;
+typedef Q_UINT64 u64bit;
+
+typedef Q_INT32 s32bit;
+}
+
+namespace Botan_types {
+
+typedef Botan::byte byte;
+typedef Botan::u32bit u32bit;
+
+}
+
+#endif
diff --git a/modules/mp_amd64/modinfo.txt b/modules/mp_amd64/modinfo.txt
new file mode 100644
index 000000000..12537da0e
--- /dev/null
+++ b/modules/mp_amd64/modinfo.txt
@@ -0,0 +1,15 @@
+realname "MPI Assembler Backend for x86-64/AMD64 Systems"
+
+mp_bits 64
+
+replace_file mp_asm.h
+replace_file mp_asmi.h
+
+<arch>
+amd64
+</arch>
+
+<cc>
+gcc
+icc
+</cc>
diff --git a/modules/mp_amd64/mp_asm.h b/modules/mp_amd64/mp_asm.h
new file mode 100644
index 000000000..17f33224c
--- /dev/null
+++ b/modules/mp_amd64/mp_asm.h
@@ -0,0 +1,84 @@
+/*************************************************
+* Lowest Level MPI Algorithms Header File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#ifndef BOTAN_MP_ASM_H__
+#define BOTAN_MP_ASM_H__
+
+#include <botan/mp_types.h>
+
+#if (BOTAN_MP_WORD_BITS != 64)
+ #error The mp_amd64 module requires that BOTAN_MP_WORD_BITS == 64
+#endif
+
+namespace Botan {
+
+extern "C" {
+
+/*************************************************
+* Word Multiply *
+*************************************************/
+inline word word_madd2(word a, word b, word c, word* carry)
+ {
+ asm(
+ "mulq %1\n\t" // a(in eax) * b(wherever) -> edx:eax
+ "addq %5,%0\n\t" // add c to low word (eax)
+ "adcq $0,%2" // add carry from previous to high word (edx)
+ : "=a"(a), "=rm"(b), "=&d"(*carry)
+ : "0"(a), "1"(b), "g"(c) : "cc");
+ return a;
+ }
+
+/*************************************************
+* Word Multiply/Add *
+*************************************************/
+inline word word_madd3(word a, word b, word c, word d, word* carry)
+ {
+ asm(
+ "mulq %1\n\t" // a(in eax) * b(wherever) -> edx:eax
+ "addq %5,%0\n\t" // add c to low word (eax)
+ "adcq $0,%2\n\t" // add carry from previous to high word (edx)
+ "addq %6,%0\n\t" // add d to low word (eax)
+ "adcq $0,%2" // add carry from previous to high word (edx)
+ : "=a"(a), "=rm"(b), "=&d"(*carry)
+ : "0"(a), "1"(b), "g"(c), "g"(d) : "cc");
+ return a;
+ }
+
+/*************************************************
+* Multiply-Add Accumulator *
+*************************************************/
+inline void word3_muladd(word* w2, word* w1, word* w0, word a, word b)
+ {
+ asm("mulq %[b]\n\t" // a(in eax) * b(wherever) -> edx:eax
+ "addq %3,%[w0]\n\t" // add c to low word (eax)
+ "adcq %4,%[w1]\n\t" // add carry from previous to high word (edx)
+ "adcq $0,%[w2]\n\t" // add carry from previous to high word (edx)
+ : [w0]"=r"(*w0), [w1]"=r"(*w1), [w2]"=r"(*w2)
+ : "a"(a), [b]"d"(b), "0"(*w0), "1"(*w1), "2"(*w2)
+ : "cc");
+ }
+
+/*************************************************
+* Multiply-Add Accumulator *
+*************************************************/
+inline void word3_muladd_2(word* w2, word* w1, word* w0, word a, word b)
+ {
+ asm("mulq %[b]\n\t" // a(in eax) * b(wherever) -> edx:eax
+ "addq %3,%[w0]\n\t" // add c to low word (eax)
+ "adcq %4,%[w1]\n\t" // add carry from previous to high word (edx)
+ "adcq $0,%[w2]\n\t" // add carry from previous to high word (edx)
+ "addq %3,%[w0]\n\t" // add c to low word (eax)
+ "adcq %4,%[w1]\n\t" // add carry from previous to high word (edx)
+ "adcq $0,%[w2]\n\t" // add carry from previous to high word (edx)
+ : [w0]"=r"(*w0), [w1]"=r"(*w1), [w2]"=r"(*w2)
+ : "a"(a), [b]"d"(b), "0"(*w0), "1"(*w1), "2"(*w2)
+ : "cc");
+ }
+
+}
+
+}
+
+#endif
diff --git a/modules/mp_amd64/mp_asmi.h b/modules/mp_amd64/mp_asmi.h
new file mode 100644
index 000000000..daa1243ca
--- /dev/null
+++ b/modules/mp_amd64/mp_asmi.h
@@ -0,0 +1,174 @@
+/*************************************************
+* Lowest Level MPI Algorithms Header File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#ifndef BOTAN_MP_ASM_INTERNAL_H__
+#define BOTAN_MP_ASM_INTERNAL_H__
+
+#include <botan/mp_types.h>
+
+namespace Botan {
+
+/*************************************************
+* Helper Macros for amd64 Assembly *
+*************************************************/
+#define ASM(x) x "\n\t"
+
+#define ADDSUB2_OP(OPERATION, INDEX) \
+ ASM("movq 8*" INDEX "(%[y]), %[carry]") \
+ ASM(OPERATION " %[carry], 8*" INDEX "(%[x])") \
+
+#define ADDSUB3_OP(OPERATION, INDEX) \
+ ASM("movq 8*" INDEX "(%[x]), %[carry]") \
+ ASM(OPERATION " 8*" INDEX "(%[y]), %[carry]") \
+ ASM("movq %[carry], 8*" INDEX "(%[z])") \
+
+#define LINMUL_OP(WRITE_TO, INDEX) \
+ ASM("movq 8*" INDEX "(%[x]),%%rax") \
+ ASM("mulq %[y]") \
+ ASM("addq %[carry],%%rax") \
+ ASM("adcq $0,%%rdx") \
+ ASM("movq %%rdx,%[carry]") \
+ ASM("movq %%rax, 8*" INDEX "(%[" WRITE_TO "])")
+
+#define MULADD_OP(IGNORED, INDEX) \
+ ASM("movq 8*" INDEX "(%[x]),%%rax") \
+ ASM("mulq %[y]") \
+ ASM("addq %[carry],%%rax") \
+ ASM("adcq $0,%%rdx") \
+ ASM("addq 8*" INDEX "(%[z]),%%rax") \
+ ASM("adcq $0,%%rdx") \
+ ASM("movq %%rdx,%[carry]") \
+ ASM("movq %%rax, 8*" INDEX " (%[z])")
+
+#define DO_8_TIMES(MACRO, ARG) \
+ MACRO(ARG, "0") MACRO(ARG, "1") MACRO(ARG, "2") MACRO(ARG, "3") \
+ MACRO(ARG, "4") MACRO(ARG, "5") MACRO(ARG, "6") MACRO(ARG, "7")
+
+#define ADD_OR_SUBTRACT(CORE_CODE) \
+ ASM("rorq %[carry]") \
+ CORE_CODE \
+ ASM("sbbq %[carry],%[carry]") \
+ ASM("negq %[carry]")
+
+/*************************************************
+* Word Addition *
+*************************************************/
+inline word word_add(word x, word y, word* carry)
+ {
+ asm(
+ ADD_OR_SUBTRACT(ASM("adcq %[y],%[x]"))
+ : [x]"=r"(x), [carry]"=r"(*carry)
+ : "0"(x), [y]"rm"(y), "1"(*carry)
+ : "cc");
+ return x;
+ }
+
+/*************************************************
+* Eight Word Block Addition, Two Argument *
+*************************************************/
+inline word word8_add2(word x[8], const word y[8], word carry)
+ {
+ asm(
+ ADD_OR_SUBTRACT(DO_8_TIMES(ADDSUB2_OP, "adcq"))
+ : [carry]"=r"(carry)
+ : [x]"r"(x), [y]"r"(y), "0"(carry)
+ : "cc", "memory");
+ return carry;
+ }
+
+/*************************************************
+* Eight Word Block Addition, Three Argument *
+*************************************************/
+inline word word8_add3(word z[8], const word x[8], const word y[8], word carry)
+ {
+ asm(
+ ADD_OR_SUBTRACT(DO_8_TIMES(ADDSUB3_OP, "adcq"))
+ : [carry]"=r"(carry)
+ : [x]"r"(x), [y]"r"(y), [z]"r"(z), "0"(carry)
+ : "cc", "memory");
+ return carry;
+ }
+
+/*************************************************
+* Word Subtraction *
+*************************************************/
+inline word word_sub(word x, word y, word* carry)
+ {
+ asm(
+ ADD_OR_SUBTRACT(ASM("sbbq %[y],%[x]"))
+ : [x]"=r"(x), [carry]"=r"(*carry)
+ : "0"(x), [y]"rm"(y), "1"(*carry)
+ : "cc");
+ return x;
+ }
+
+/*************************************************
+* Eight Word Block Subtraction, Two Argument *
+*************************************************/
+inline word word8_sub2(word x[8], const word y[8], word carry)
+ {
+ asm(
+ ADD_OR_SUBTRACT(DO_8_TIMES(ADDSUB2_OP, "sbbq"))
+ : [carry]"=r"(carry)
+ : [x]"r"(x), [y]"r"(y), "0"(carry)
+ : "cc", "memory");
+ return carry;
+ }
+
+/*************************************************
+* Eight Word Block Subtraction, Three Argument *
+*************************************************/
+inline word word8_sub3(word z[8], const word x[8], const word y[8], word carry)
+ {
+ asm(
+ ADD_OR_SUBTRACT(DO_8_TIMES(ADDSUB3_OP, "sbbq"))
+ : [carry]"=r"(carry)
+ : [x]"r"(x), [y]"r"(y), [z]"r"(z), "0"(carry)
+ : "cc", "memory");
+ return carry;
+ }
+
+/*************************************************
+* Eight Word Block Linear Multiplication *
+*************************************************/
+inline word word8_linmul2(word x[8], word y, word carry)
+ {
+ asm(
+ DO_8_TIMES(LINMUL_OP, "x")
+ : [carry]"=r"(carry)
+ : [x]"r"(x), [y]"rm"(y), "0"(carry)
+ : "cc", "%rax", "%rdx");
+ return carry;
+ }
+
+/*************************************************
+* Eight Word Block Linear Multiplication *
+*************************************************/
+inline word word8_linmul3(word z[8], const word x[8], word y, word carry)
+ {
+ asm(
+ DO_8_TIMES(LINMUL_OP, "z")
+ : [carry]"=r"(carry)
+ : [z]"r"(z), [x]"r"(x), [y]"rm"(y), "0"(carry)
+ : "cc", "%rax", "%rdx");
+ return carry;
+ }
+
+/*************************************************
+* Eight Word Block Multiply/Add *
+*************************************************/
+inline word word8_madd3(word z[8], const word x[8], word y, word carry)
+ {
+ asm(
+ DO_8_TIMES(MULADD_OP, "")
+ : [carry]"=r"(carry)
+ : [z]"r"(z), [x]"r"(x), [y]"rm"(y), "0"(carry)
+ : "cc", "%rax", "%rdx");
+ return carry;
+ }
+
+}
+
+#endif
diff --git a/modules/mp_asm64/modinfo.txt b/modules/mp_asm64/modinfo.txt
new file mode 100644
index 000000000..203608d9e
--- /dev/null
+++ b/modules/mp_asm64/modinfo.txt
@@ -0,0 +1,23 @@
+realname "MPI Assembler Backend for 64 bit Systems"
+
+mp_bits 64
+
+replace_file mp_asm.h
+
+# Disable amd64 since (nominally) the mp_amd64 module has that covered
+<arch>
+alpha
+# amd64
+ia64
+mips64
+ppc64
+sparc64
+</arch>
+
+# The inline asm only works with gcc, but it looks like (at least on
+# UltraSPARC), using 64-bit words and the sythensized multiply is a 5 to 25%
+# win, so it's probably worth using elsewhere.
+<cc>
+gcc
+sunwspro
+</cc>
diff --git a/modules/mp_asm64/mp_asm.h b/modules/mp_asm64/mp_asm.h
new file mode 100644
index 000000000..8c6df078e
--- /dev/null
+++ b/modules/mp_asm64/mp_asm.h
@@ -0,0 +1,119 @@
+/*************************************************
+* MPI Multiply-Add Core Header File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#ifndef BOTAN_MP_MADD_H__
+#define BOTAN_MP_MADD_H__
+
+#include <botan/mp_types.h>
+
+#if (BOTAN_MP_WORD_BITS != 64)
+ #error The mp_asm64 module requires that BOTAN_MP_WORD_BITS == 64
+#endif
+
+#if defined(BOTAN_TARGET_ARCH_IS_AMD64)
+
+#define BOTAN_WORD_MUL(a,b,z1,z0) do { \
+ asm("mulq %3" : "=d" (z0), "=a" (z1) : \
+ "a" (a), "rm" (b) : "cc"); \
+} while(0);
+
+#elif defined(BOTAN_TARGET_ARCH_IS_ALPHA)
+
+#define BOTAN_WORD_MUL(a,b,z1,z0) do { \
+ asm("umulh %1,%2,%0" : "=r" (z0) : "r" (a), "r" (b)); \
+ z1 = a * b; \
+} while(0);
+
+#elif defined(BOTAN_TARGET_ARCH_IS_IA64)
+
+#define BOTAN_WORD_MUL(a,b,z1,z0) do { \
+ asm("xmpy.hu %0=%1,%2" : "=f" (z0) : "f" (a), "f" (b)); \
+ z1 = a * b; \
+} while(0);
+
+#elif defined(BOTAN_TARGET_ARCH_IS_PPC64)
+
+#define BOTAN_WORD_MUL(a,b,z1,z0) do { \
+ asm("mulhdu %0,%1,%2" : "=r" (z0) : "r" (a), "r" (b) : "cc"); \
+ z1 = a * b; \
+} while(0);
+
+#elif defined(BOTAN_TARGET_ARCH_IS_MIPS64)
+
+#define BOTAN_WORD_MUL(a,b,z1,z0) do { \
+ asm("dmultu %2,%3" : "=h" (z0), "=l" (z1) : "r" (a), "r" (b)); \
+} while(0);
+
+#else
+
+#include <botan/mp_core.h>
+
+#define BOTAN_WORD_MUL(a,b,z1,z0) \
+ do { bigint_wordmul(a, b, &z1, &z0); } while(0);
+
+#endif
+
+namespace Botan {
+
+/*************************************************
+* Word Multiply/Add *
+*************************************************/
+inline word word_madd2(word a, word b, word c, word* carry)
+ {
+ word z0 = 0, z1 = 0;
+
+ BOTAN_WORD_MUL(a, b, z1, z0);
+
+ z1 += c; if(z1 < c) z0++;
+
+ *carry = z0;
+ return z1;
+ }
+
+/*************************************************
+* Word Multiply/Add *
+*************************************************/
+inline word word_madd3(word a, word b, word c, word d, word* carry)
+ {
+ word z0 = 0, z1 = 0;
+
+ BOTAN_WORD_MUL(a, b, z1, z0);
+
+ z1 += c; if(z1 < c) z0++;
+ z1 += d; if(z1 < d) z0++;
+
+ *carry = z0;
+ return z1;
+ }
+
+/*************************************************
+* Multiply-Add Accumulator *
+*************************************************/
+inline void word3_muladd(word* w2, word* w1, word* w0, word a, word b)
+ {
+ *w0 = word_madd2(a, b, *w0, &a);
+ *w1 += a;
+ *w2 += (*w1 < a) ? 1 : 0;
+ }
+
+/*************************************************
+* Multiply-Add Accumulator *
+*************************************************/
+inline void word3_muladd_2(word* w2, word* w1, word* w0, word a, word b)
+ {
+ a = word_madd2(a, b, 0, &b);
+
+ *w0 += a;
+ *w1 += b + ((*w0 < a) ? 1 : 0);
+ *w2 += (*w1 < b) ? 1 : 0;
+
+ *w0 += a;
+ *w1 += b + ((*w0 < a) ? 1 : 0);
+ *w2 += (*w1 < b) ? 1 : 0;
+ }
+
+}
+
+#endif
diff --git a/modules/mp_ia32/modinfo.txt b/modules/mp_ia32/modinfo.txt
new file mode 100644
index 000000000..ff2114fd8
--- /dev/null
+++ b/modules/mp_ia32/modinfo.txt
@@ -0,0 +1,15 @@
+realname "MPI Assembler Backend for x86 Systems"
+
+mp_bits 32
+
+replace_file mp_asm.h
+replace_file mp_asmi.h
+
+<arch>
+ia32
+</arch>
+
+<cc>
+gcc
+icc
+</cc>
diff --git a/modules/mp_ia32/mp_asm.h b/modules/mp_ia32/mp_asm.h
new file mode 100644
index 000000000..8fb4af8fb
--- /dev/null
+++ b/modules/mp_ia32/mp_asm.h
@@ -0,0 +1,88 @@
+/*************************************************
+* Lowest Level MPI Algorithms Header File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#ifndef BOTAN_MP_ASM_H__
+#define BOTAN_MP_ASM_H__
+
+#include <botan/mp_types.h>
+
+#if (BOTAN_MP_WORD_BITS != 32)
+ #error The mp_ia32 module requires that BOTAN_MP_WORD_BITS == 32
+#endif
+
+namespace Botan {
+
+extern "C" {
+
+/*************************************************
+* Word Multiply *
+*************************************************/
+inline word word_madd2(word a, word b, word c, word* carry)
+ {
+ asm(
+ "mull %1\n\t" // a (eax) * b (anywhere) -> edx:eax
+ "addl %5,%0\n\t" // add c to low word (eax)
+ "adcl $0,%2" // add carry from previous to high word (edx)
+ : "=a"(a), "=rm"(b), "=&d"(*carry)
+ : "0"(a), "1"(b), "g"(c) : "cc");
+
+ return a;
+ }
+
+/*************************************************
+* Word Multiply/Add *
+*************************************************/
+inline word word_madd3(word a, word b, word c, word d, word* carry)
+ {
+ asm(
+ "mull %1\n\t" // a (eax) * b (anywhere) -> edx:eax
+ "addl %5,%0\n\t" // add c to low word (eax)
+ "adcl $0,%2\n\t" // add carry from previous add to high word (edx)
+ "addl %6,%0\n\t" // add d to low word (eax)
+ "adcl $0,%2" // add carry from previous add to high word (edx)
+ : "=a"(a), "=rm"(b), "=&d"(*carry)
+ : "0"(a), "1"(b), "g"(c), "g"(d) : "cc");
+
+ return a;
+ }
+
+/*************************************************
+* Multiply-Add Accumulator *
+*************************************************/
+inline void word3_muladd(word* w2, word* w1, word* w0, word x, word y)
+ {
+ asm(
+ "mull %[y]\n\t" // a (eax) * b (anywhere) -> edx:eax
+ "addl %3,%[w0]\n\t" // add c to low word (eax)
+ "adcl %4,%[w1]\n\t" // add carry from previous add to high word (edx)
+ "adcl $0,%[w2]\n\t" // add carry from previous add to high word (edx)
+ : [w0]"=r"(*w0), [w1]"=r"(*w1), [w2]"=r"(*w2)
+ : "a"(x), [y]"d"(y), "0"(*w0), "1"(*w1), "2"(*w2)
+ : "cc");
+ }
+
+/*************************************************
+* Multiply-Add Accumulator *
+*************************************************/
+inline void word3_muladd_2(word* w2, word* w1, word* w0, word x, word y)
+ {
+ asm(
+ "mull %[y]\n\t" // a (eax) * b (anywhere) -> edx:eax
+ "addl %3,%[w0]\n\t" // add c to low word (eax)
+ "adcl %4,%[w1]\n\t" // add carry from previous add to high word (edx)
+ "adcl $0,%[w2]\n\t" // add carry from previous add to high word (edx)
+ "addl %3,%[w0]\n\t" // add c to low word (eax)
+ "adcl %4,%[w1]\n\t" // add carry from previous add to high word (edx)
+ "adcl $0,%[w2]\n\t" // add carry from previous add to high word (edx)
+ : [w0]"=r"(*w0), [w1]"=r"(*w1), [w2]"=r"(*w2)
+ : "a"(x), [y]"d"(y), "0"(*w0), "1"(*w1), "2"(*w2)
+ : "cc");
+ }
+
+}
+
+}
+
+#endif
diff --git a/modules/mp_ia32/mp_asmi.h b/modules/mp_ia32/mp_asmi.h
new file mode 100644
index 000000000..a0e5a82e4
--- /dev/null
+++ b/modules/mp_ia32/mp_asmi.h
@@ -0,0 +1,174 @@
+/*************************************************
+* Lowest Level MPI Algorithms Header File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#ifndef BOTAN_MP_ASM_INTERNAL_H__
+#define BOTAN_MP_ASM_INTERNAL_H__
+
+#include <botan/mp_types.h>
+
+namespace Botan {
+
+/*************************************************
+* Helper Macros for x86 Assembly *
+*************************************************/
+#define ASM(x) x "\n\t"
+
+#define ADDSUB2_OP(OPERATION, INDEX) \
+ ASM("movl 4*" INDEX "(%[y]), %[carry]") \
+ ASM(OPERATION " %[carry], 4*" INDEX "(%[x])") \
+
+#define ADDSUB3_OP(OPERATION, INDEX) \
+ ASM("movl 4*" INDEX "(%[x]), %[carry]") \
+ ASM(OPERATION " 4*" INDEX "(%[y]), %[carry]") \
+ ASM("movl %[carry], 4*" INDEX "(%[z])") \
+
+#define LINMUL_OP(WRITE_TO, INDEX) \
+ ASM("movl 4*" INDEX "(%[x]),%%eax") \
+ ASM("mull %[y]") \
+ ASM("addl %[carry],%%eax") \
+ ASM("adcl $0,%%edx") \
+ ASM("movl %%edx,%[carry]") \
+ ASM("movl %%eax, 4*" INDEX "(%[" WRITE_TO "])")
+
+#define MULADD_OP(IGNORED, INDEX) \
+ ASM("movl 4*" INDEX "(%[x]),%%eax") \
+ ASM("mull %[y]") \
+ ASM("addl %[carry],%%eax") \
+ ASM("adcl $0,%%edx") \
+ ASM("addl 4*" INDEX "(%[z]),%%eax") \
+ ASM("adcl $0,%%edx") \
+ ASM("movl %%edx,%[carry]") \
+ ASM("movl %%eax, 4*" INDEX " (%[z])")
+
+#define DO_8_TIMES(MACRO, ARG) \
+ MACRO(ARG, "0") MACRO(ARG, "1") MACRO(ARG, "2") MACRO(ARG, "3") \
+ MACRO(ARG, "4") MACRO(ARG, "5") MACRO(ARG, "6") MACRO(ARG, "7")
+
+#define ADD_OR_SUBTRACT(CORE_CODE) \
+ ASM("rorl %[carry]") \
+ CORE_CODE \
+ ASM("sbbl %[carry],%[carry]") \
+ ASM("negl %[carry]")
+
+/*************************************************
+* Word Addition *
+*************************************************/
+inline word word_add(word x, word y, word* carry)
+ {
+ asm(
+ ADD_OR_SUBTRACT(ASM("adcl %[y],%[x]"))
+ : [x]"=r"(x), [carry]"=r"(*carry)
+ : "0"(x), [y]"rm"(y), "1"(*carry)
+ : "cc");
+ return x;
+ }
+
+/*************************************************
+* Eight Word Block Addition, Two Argument *
+*************************************************/
+inline word word8_add2(word x[8], const word y[8], word carry)
+ {
+ asm(
+ ADD_OR_SUBTRACT(DO_8_TIMES(ADDSUB2_OP, "adcl"))
+ : [carry]"=r"(carry)
+ : [x]"r"(x), [y]"r"(y), "0"(carry)
+ : "cc", "memory");
+ return carry;
+ }
+
+/*************************************************
+* Eight Word Block Addition, Three Argument *
+*************************************************/
+inline word word8_add3(word z[8], const word x[8], const word y[8], word carry)
+ {
+ asm(
+ ADD_OR_SUBTRACT(DO_8_TIMES(ADDSUB3_OP, "adcl"))
+ : [carry]"=r"(carry)
+ : [x]"r"(x), [y]"r"(y), [z]"r"(z), "0"(carry)
+ : "cc", "memory");
+ return carry;
+ }
+
+/*************************************************
+* Word Subtraction *
+*************************************************/
+inline word word_sub(word x, word y, word* carry)
+ {
+ asm(
+ ADD_OR_SUBTRACT(ASM("sbbl %[y],%[x]"))
+ : [x]"=r"(x), [carry]"=r"(*carry)
+ : "0"(x), [y]"rm"(y), "1"(*carry)
+ : "cc");
+ return x;
+ }
+
+/*************************************************
+* Eight Word Block Subtraction, Two Argument *
+*************************************************/
+inline word word8_sub2(word x[8], const word y[8], word carry)
+ {
+ asm(
+ ADD_OR_SUBTRACT(DO_8_TIMES(ADDSUB2_OP, "sbbl"))
+ : [carry]"=r"(carry)
+ : [x]"r"(x), [y]"r"(y), "0"(carry)
+ : "cc", "memory");
+ return carry;
+ }
+
+/*************************************************
+* Eight Word Block Subtraction, Three Argument *
+*************************************************/
+inline word word8_sub3(word z[8], const word x[8], const word y[8], word carry)
+ {
+ asm(
+ ADD_OR_SUBTRACT(DO_8_TIMES(ADDSUB3_OP, "sbbl"))
+ : [carry]"=r"(carry)
+ : [x]"r"(x), [y]"r"(y), [z]"r"(z), "0"(carry)
+ : "cc", "memory");
+ return carry;
+ }
+
+/*************************************************
+* Eight Word Block Linear Multiplication *
+*************************************************/
+inline word word8_linmul2(word x[8], word y, word carry)
+ {
+ asm(
+ DO_8_TIMES(LINMUL_OP, "x")
+ : [carry]"=r"(carry)
+ : [x]"r"(x), [y]"rm"(y), "0"(carry)
+ : "cc", "%eax", "%edx");
+ return carry;
+ }
+
+/*************************************************
+* Eight Word Block Linear Multiplication *
+*************************************************/
+inline word word8_linmul3(word z[8], const word x[8], word y, word carry)
+ {
+ asm(
+ DO_8_TIMES(LINMUL_OP, "z")
+ : [carry]"=r"(carry)
+ : [z]"r"(z), [x]"r"(x), [y]"rm"(y), "0"(carry)
+ : "cc", "%eax", "%edx");
+ return carry;
+ }
+
+/*************************************************
+* Eight Word Block Multiply/Add *
+*************************************************/
+inline word word8_madd3(word z[8], const word x[8], word y, word carry)
+ {
+ asm(
+ DO_8_TIMES(MULADD_OP, "")
+ : [carry]"=r"(carry)
+ : [z]"r"(z), [x]"r"(x), [y]"rm"(y), "0"(carry)
+ : "cc", "%eax", "%edx");
+ return carry;
+ }
+
+}
+
+#endif
diff --git a/modules/mp_ia32_msvc/modinfo.txt b/modules/mp_ia32_msvc/modinfo.txt
new file mode 100644
index 000000000..835a68d9f
--- /dev/null
+++ b/modules/mp_ia32_msvc/modinfo.txt
@@ -0,0 +1,13 @@
+realname "MPI Assembler Backend for x86 Systems"
+
+mp_bits 32
+
+replace_file mp_asmi.h
+
+<arch>
+ia32
+</arch>
+
+<cc>
+msvc
+</cc>
diff --git a/modules/mp_ia32_msvc/mp_asmi.h b/modules/mp_ia32_msvc/mp_asmi.h
new file mode 100644
index 000000000..ad1451010
--- /dev/null
+++ b/modules/mp_ia32_msvc/mp_asmi.h
@@ -0,0 +1,486 @@
+/*************************************************
+* Lowest Level MPI Algorithms Header File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#ifndef BOTAN_MP_ASM_INTERNAL_H__
+#define BOTAN_MP_ASM_INTERNAL_H__
+
+#include <botan/mp_asm.h>
+
+namespace Botan {
+
+extern "C" {
+
+/*************************************************
+* Word Addition *
+*************************************************/
+inline word word_add(word x, word y, word* carry)
+ {
+ word z = x + y;
+ word c1 = (z < x);
+ z += *carry;
+ *carry = c1 | (z < *carry);
+ return z;
+ }
+
+/*************************************************
+* Four Word Block Addition, Two Argument *
+*************************************************/
+inline word word4_addcarry(word x[4], word carry)
+ {
+ __asm {
+ mov edx,[x]
+ xor eax,eax
+ sub eax,[carry] //force CF=1 iff *carry==1
+ adc [edx],0
+ mov eax,[esi+4]
+ adc [edx+4],0
+ mov eax,[esi+8]
+ adc [edx+8],0
+ mov eax,[esi+12]
+ adc [edx+12],0
+ sbb eax,eax
+ neg eax
+ }
+ }
+
+ /*************************************************
+* Four Word Block Addition, Two Argument *
+*************************************************/
+inline word word8_add2(word x[8], const word y[8], word carry)
+ {
+ __asm {
+ mov edx,[x]
+ mov esi,[y]
+ xor eax,eax
+ sub eax,[carry] //force CF=1 iff *carry==1
+ mov eax,[esi]
+ adc [edx],eax
+ mov eax,[esi+4]
+ adc [edx+4],eax
+ mov eax,[esi+8]
+ adc [edx+8],eax
+ mov eax,[esi+12]
+ adc [edx+12],eax
+ mov eax,[esi+16]
+ adc [edx+16],eax
+ mov eax,[esi+20]
+ adc [edx+20],eax
+ mov eax,[esi+24]
+ adc [edx+24],eax
+ mov eax,[esi+28]
+ adc [edx+28],eax
+ sbb eax,eax
+ neg eax
+ }
+ }
+
+/*************************************************
+* Four Word Block Addition, Three Argument *
+*************************************************/
+inline word word8_add3(word z[8], const word x[8], const word y[8], word carry)
+ {
+ __asm {
+ mov edi,[x]
+ mov esi,[y]
+ mov ebx,[z]
+ xor eax,eax
+ sub eax,[carry] //force CF=1 iff *carry==1
+ mov eax,[edi]
+ adc eax,[esi]
+ mov [ebx],eax
+
+ mov eax,[edi+4]
+ adc eax,[esi+4]
+ mov [ebx+4],eax
+
+ mov eax,[edi+8]
+ adc eax,[esi+8]
+ mov [ebx+8],eax
+
+ mov eax,[edi+12]
+ adc eax,[esi+12]
+ mov [ebx+12],eax
+
+ mov eax,[edi+16]
+ adc eax,[esi+16]
+ mov [ebx+16],eax
+
+ mov eax,[edi+20]
+ adc eax,[esi+20]
+ mov [ebx+20],eax
+
+ mov eax,[edi+24]
+ adc eax,[esi+24]
+ mov [ebx+24],eax
+
+ mov eax,[edi+28]
+ adc eax,[esi+28]
+ mov [ebx+28],eax
+
+ sbb eax,eax
+ neg eax
+ }
+ }
+
+/*************************************************
+* Word Subtraction *
+*************************************************/
+inline word word_sub(word x, word y, word* carry)
+ {
+ word t0 = x - y;
+ word c1 = (t0 > x);
+ word z = t0 - *carry;
+ *carry = c1 | (z > t0);
+ return z;
+ }
+
+/*************************************************
+* Four Word Block Subtraction, Two Argument *
+*************************************************/
+inline word word8_sub2(word x[8], const word y[8], word carry)
+ {
+ _asm {
+ mov edi,[x]
+ mov esi,[y]
+ xor eax,eax
+ sub eax,[carry] //force CF=1 iff *carry==1
+ mov eax,[edi]
+ sbb eax,[esi]
+ mov [edi],eax
+ mov eax,[edi+4]
+ sbb eax,[esi+4]
+ mov [edi+4],eax
+ mov eax,[edi+8]
+ sbb eax,[esi+8]
+ mov [edi+8],eax
+ mov eax,[edi+12]
+ sbb eax,[esi+12]
+ mov [edi+12],eax
+ mov eax,[edi+16]
+ sbb eax,[esi+16]
+ mov [edi+16],eax
+ mov eax,[edi+20]
+ sbb eax,[esi+20]
+ mov [edi+20],eax
+ mov eax,[edi+24]
+ sbb eax,[esi+24]
+ mov [edi+24],eax
+ mov eax,[edi+28]
+ sbb eax,[esi+28]
+ mov [edi+28],eax
+ sbb eax,eax
+ neg eax
+ }
+ }
+
+/*************************************************
+* Four Word Block Subtraction, Three Argument *
+*************************************************/
+__forceinline word word8_sub3(word z[8], const word x[8],
+ const word y[8], word carry)
+ {
+ __asm
+ {
+ mov edi,[x]
+ mov esi,[y]
+ xor eax,eax
+ sub eax,[carry] //force CF=1 iff *carry==1
+ mov ebx,[z]
+ mov eax,[edi]
+ sbb eax,[esi]
+ mov [ebx],eax
+ mov eax,[edi+4]
+ sbb eax,[esi+4]
+ mov [ebx+4],eax
+ mov eax,[edi+8]
+ sbb eax,[esi+8]
+ mov [ebx+8],eax
+ mov eax,[edi+12]
+ sbb eax,[esi+12]
+ mov [ebx+12],eax
+ mov eax,[edi+16]
+ sbb eax,[esi+16]
+ mov [ebx+16],eax
+ mov eax,[edi+20]
+ sbb eax,[esi+20]
+ mov [ebx+20],eax
+ mov eax,[edi+24]
+ sbb eax,[esi+24]
+ mov [ebx+24],eax
+ mov eax,[edi+28]
+ sbb eax,[esi+28]
+ mov [ebx+28],eax
+ sbb eax,eax
+ neg eax
+ }
+ }
+
+/*************************************************
+* Four Word Block Linear Multiplication *
+*************************************************/
+inline word word4_linmul2(word x[4], word y, word carry)
+{
+ __asm
+ {
+ mov esi,[x]
+ mov eax,[esi] //load a
+ mul [y] //edx(hi):eax(lo)=a*b
+ add eax,[carry] //sum lo carry
+ adc edx,0 //sum hi carry
+ mov ecx,edx //store carry
+ mov [esi],eax //load a
+
+ mov eax,[esi+4] //load a
+ mul [y] //edx(hi):eax(lo)=a*b
+ add eax,ecx //sum lo carry
+ adc edx,0 //sum hi carry
+ mov ecx,edx //store carry
+ mov [esi+4],eax //load a
+
+ mov eax,[esi+8] //load a
+ mul [y] //edx(hi):eax(lo)=a*b
+ add eax,ecx //sum lo carry
+ adc edx,0 //sum hi carry
+ mov ecx,edx //store carry
+ mov [esi+8],eax //load a
+
+ mov eax,[esi+12] //load a
+ mul [y] //edx(hi):eax(lo)=a*b
+ add eax,ecx //sum lo carry
+ adc edx,0 //sum hi carry
+ mov [esi+12],eax //load a
+ mov eax,edx //store carry
+ }
+ }
+
+/*************************************************
+* Eight Word Block Linear Multiplication *
+*************************************************/
+
+__forceinline word word8_muladd(word z[8], const word x[8], word y, word carry)
+ {
+ __asm
+ {
+ mov esi,[x]
+ mov ebx,[y]
+ mov edi,[z]
+ mov eax,[esi] //load a
+ mul ebx //edx(hi):eax(lo)=a*b
+ add eax,[carry] //sum lo carry
+ adc edx,0 //sum hi carry
+ add eax,[edi] //sum lo z
+ adc edx,0 //sum hi z
+ mov ecx,edx //carry for next block = hi z
+ mov [edi],eax //save lo z
+
+ mov eax,[esi+4]
+ mul ebx
+ add eax,ecx
+ adc edx,0
+ add eax,[edi+4]
+ adc edx,0
+ mov ecx,edx
+ mov [edi+4],eax
+
+ mov eax,[esi+8]
+ mul ebx
+ add eax,ecx
+ adc edx,0
+ add eax,[edi+8]
+ adc edx,0
+ mov ecx,edx
+ mov [edi+8],eax
+
+ mov eax,[esi+12]
+ mul ebx
+ add eax,ecx
+ adc edx,0
+ add eax,[edi+12]
+ adc edx,0
+ mov ecx,edx
+ mov [edi+12],eax
+
+ mov eax,[esi+16]
+ mul ebx
+ add eax,ecx
+ adc edx,0
+ add eax,[edi+16]
+ adc edx,0
+ mov ecx,edx
+ mov [edi+16],eax
+
+ mov eax,[esi+20]
+ mul ebx
+ add eax,ecx
+ adc edx,0
+ add eax,[edi+20]
+ adc edx,0
+ mov ecx,edx
+ mov [edi+20],eax
+
+ mov eax,[esi+24]
+ mul ebx
+ add eax,ecx
+ adc edx,0
+ add eax,[edi+24]
+ adc edx,0
+ mov ecx,edx
+ mov [edi+24],eax
+
+ mov eax,[esi+28]
+ mul ebx
+ add eax,ecx
+ adc edx,0
+ add eax,[edi+28]
+ adc edx,0
+ mov [edi+28],eax
+ mov eax,edx
+ }
+ }
+
+__forceinline word word8_linmul3(word z[4], const word x[4], word y, word carry)
+ {
+ __asm
+ {
+#if 0
+ //it's slower!!!
+ mov edx,[z]
+ mov eax,[x]
+ movd mm7,[y]
+
+ movd mm0,[eax]
+ movd mm1,[eax+4]
+ movd mm2,[eax+8]
+ pmuludq mm0,mm7
+ pmuludq mm1,mm7
+ pmuludq mm2,mm7
+
+ movd mm6,[carry]
+ paddq mm0,mm6
+ movd [edx],mm0
+
+ psrlq mm0,32
+ paddq mm1,mm0
+ movd [edx+4],mm1
+
+ movd mm3,[eax+12]
+ psrlq mm1,32
+ paddq mm2,mm1
+ movd [edx+8],mm2
+
+ pmuludq mm3,mm7
+ movd mm4,[eax+16]
+ psrlq mm2,32
+ paddq mm3,mm2
+ movd [edx+12],mm3
+
+ pmuludq mm4,mm7
+ movd mm5,[eax+20]
+ psrlq mm3,32
+ paddq mm4,mm3
+ movd [edx+16],mm4
+
+ pmuludq mm5,mm7
+ movd mm0,[eax+24]
+ psrlq mm4,32
+ paddq mm5,mm4
+ movd [edx+20],mm5
+
+ pmuludq mm0,mm7
+ movd mm1,[eax+28]
+ psrlq mm5,32
+ paddq mm0,mm5
+ movd [edx+24],mm0
+
+ pmuludq mm1,mm7
+ psrlq mm0,32
+ paddq mm1,mm0
+ movd [edx+28],mm1
+
+ psrlq mm1,32
+ movd eax,mm1
+ emms
+#else
+ mov edi,[z]
+ mov esi,[x]
+ mov eax,[esi] //load a
+ mul [y] //edx(hi):eax(lo)=a*b
+ add eax,[carry] //sum lo carry
+ adc edx,0 //sum hi carry
+ mov ecx,edx //store carry
+ mov [edi],eax //load a
+
+ mov eax,[esi+4] //load a
+ mul [y] //edx(hi):eax(lo)=a*b
+ add eax,ecx //sum lo carry
+ adc edx,0 //sum hi carry
+ mov ecx,edx //store carry
+ mov [edi+4],eax //load a
+
+ mov eax,[esi+8] //load a
+ mul [y] //edx(hi):eax(lo)=a*b
+ add eax,ecx //sum lo carry
+ adc edx,0 //sum hi carry
+ mov ecx,edx //store carry
+ mov [edi+8],eax //load a
+
+ mov eax,[esi+12] //load a
+ mul [y] //edx(hi):eax(lo)=a*b
+ add eax,ecx //sum lo carry
+ adc edx,0 //sum hi carry
+ mov ecx,edx //store carry
+ mov [edi+12],eax //load a
+
+ mov eax,[esi+16] //load a
+ mul [y] //edx(hi):eax(lo)=a*b
+ add eax,ecx //sum lo carry
+ adc edx,0 //sum hi carry
+ mov ecx,edx //store carry
+ mov [edi+16],eax //load a
+
+ mov eax,[esi+20] //load a
+ mul [y] //edx(hi):eax(lo)=a*b
+ add eax,ecx //sum lo carry
+ adc edx,0 //sum hi carry
+ mov ecx,edx //store carry
+ mov [edi+20],eax //load a
+
+ mov eax,[esi+24] //load a
+ mul [y] //edx(hi):eax(lo)=a*b
+ add eax,ecx //sum lo carry
+ adc edx,0 //sum hi carry
+ mov ecx,edx //store carry
+ mov [edi+24],eax //load a
+
+ mov eax,[esi+28] //load a
+ mul [y] //edx(hi):eax(lo)=a*b
+ add eax,ecx //sum lo carry
+ adc edx,0 //sum hi carry
+ mov [edi+28],eax //load a
+ mov eax,edx //store carry
+#endif
+ }
+ }
+
+/*************************************************
+* Eight Word Block Multiply-Add *
+*************************************************/
+inline void word8_madd3(word z[], word x, const word y[], word* carry)
+ {
+ word_madd(x, y[0], z[0], *carry, z + 0, carry);
+ word_madd(x, y[1], z[1], *carry, z + 1, carry);
+ word_madd(x, y[2], z[2], *carry, z + 2, carry);
+ word_madd(x, y[3], z[3], *carry, z + 3, carry);
+ word_madd(x, y[4], z[4], *carry, z + 4, carry);
+ word_madd(x, y[5], z[5], *carry, z + 5, carry);
+ word_madd(x, y[6], z[6], *carry, z + 6, carry);
+ word_madd(x, y[7], z[7], *carry, z + 7, carry);
+ }
+
+}
+
+}
+
+#endif
diff --git a/modules/mux_pthr/modinfo.txt b/modules/mux_pthr/modinfo.txt
new file mode 100644
index 000000000..0aeca05d6
--- /dev/null
+++ b/modules/mux_pthr/modinfo.txt
@@ -0,0 +1,25 @@
+realname "Pthread Mutex"
+
+define MUTEX_PTHREAD
+
+add_file mux_pthr.cpp
+add_file mux_pthr.h
+
+<libs>
+all!qnx,freebsd,openbsd,netbsd -> pthread
+</libs>
+
+<os>
+aix
+cygwin
+darwin
+freebsd
+hpux
+irix
+linux
+netbsd
+openbsd
+qnx
+solaris
+tru64
+</os>
diff --git a/modules/mux_pthr/mux_pthr.cpp b/modules/mux_pthr/mux_pthr.cpp
new file mode 100644
index 000000000..ec2308fae
--- /dev/null
+++ b/modules/mux_pthr/mux_pthr.cpp
@@ -0,0 +1,62 @@
+/*************************************************
+* Pthread Mutex Source File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#include <botan/mux_pthr.h>
+#include <botan/exceptn.h>
+
+#ifndef _POSIX_C_SOURCE
+ #define _POSIX_C_SOURCE 199506
+#endif
+
+#include <pthread.h>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* Pthread Mutex *
+*************************************************/
+class Pthread_Mutex : public Mutex
+ {
+ public:
+ void lock()
+ {
+ if(pthread_mutex_lock(&mutex) != 0)
+ throw Exception("Pthread_Mutex::lock: Error occured");
+ }
+
+ void unlock()
+ {
+ if(pthread_mutex_unlock(&mutex) != 0)
+ throw Exception("Pthread_Mutex::unlock: Error occured");
+ }
+
+ Pthread_Mutex()
+ {
+ if(pthread_mutex_init(&mutex, 0) != 0)
+ throw Exception("Pthread_Mutex: initialization failed");
+ }
+
+ ~Pthread_Mutex()
+ {
+ if(pthread_mutex_destroy(&mutex) != 0)
+ throw Invalid_State("~Pthread_Mutex: mutex is still locked");
+ }
+ private:
+ pthread_mutex_t mutex;
+ };
+
+}
+
+/*************************************************
+* Pthread Mutex Factory *
+*************************************************/
+Mutex* Pthread_Mutex_Factory::make()
+ {
+ return new Pthread_Mutex();
+ }
+
+}
diff --git a/modules/mux_pthr/mux_pthr.h b/modules/mux_pthr/mux_pthr.h
new file mode 100644
index 000000000..47503d390
--- /dev/null
+++ b/modules/mux_pthr/mux_pthr.h
@@ -0,0 +1,24 @@
+/*************************************************
+* Pthread Mutex Header File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#ifndef BOTAN_EXT_MUTEX_PTHREAD_H__
+#define BOTAN_EXT_MUTEX_PTHREAD_H__
+
+#include <botan/mutex.h>
+
+namespace Botan {
+
+/*************************************************
+* Pthread Mutex Factory *
+*************************************************/
+class Pthread_Mutex_Factory : public Mutex_Factory
+ {
+ public:
+ Mutex* make();
+ };
+
+}
+
+#endif
diff --git a/modules/mux_win32/modinfo.txt b/modules/mux_win32/modinfo.txt
new file mode 100644
index 000000000..ed8d688b3
--- /dev/null
+++ b/modules/mux_win32/modinfo.txt
@@ -0,0 +1,11 @@
+realname "Win32 Mutex"
+
+define MUTEX_WIN32
+
+add_file mux_win32.cpp
+add_file mux_win32.h
+
+<os>
+cygwin
+windows
+</os>
diff --git a/modules/mux_win32/mux_win32.cpp b/modules/mux_win32/mux_win32.cpp
new file mode 100644
index 000000000..400aea183
--- /dev/null
+++ b/modules/mux_win32/mux_win32.cpp
@@ -0,0 +1,39 @@
+/*************************************************
+* Win32 Mutex Source File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#include <botan/mux_win32.h>
+#include <botan/exceptn.h>
+#include <windows.h>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* Win32 Mutex *
+*************************************************/
+class Win32_Mutex : public Mutex
+ {
+ public:
+ void lock() { EnterCriticalSection(&mutex); }
+ void unlock() { LeaveCriticalSection(&mutex); }
+
+ Win32_Mutex() { InitializeCriticalSection(&mutex); }
+ ~Win32_Mutex() { DeleteCriticalSection(&mutex); }
+ private:
+ CRITICAL_SECTION mutex;
+ };
+
+}
+
+/*************************************************
+* Win32 Mutex Factory *
+*************************************************/
+Mutex* Win32_Mutex_Factory::make()
+ {
+ return new Win32_Mutex();
+ }
+
+}
diff --git a/modules/mux_win32/mux_win32.h b/modules/mux_win32/mux_win32.h
new file mode 100644
index 000000000..7ff1276aa
--- /dev/null
+++ b/modules/mux_win32/mux_win32.h
@@ -0,0 +1,23 @@
+/*************************************************
+* Win32 Mutex Header File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#ifndef BOTAN_EXT_MUTEX_WIN32_H__
+#define BOTAN_EXT_MUTEX_WIN32_H__
+
+#include <botan/mutex.h>
+
+namespace Botan {
+
+/*************************************************
+* Win32 Mutex Factory *
+*************************************************/
+class Win32_Mutex_Factory : public Mutex_Factory
+ {
+ public:
+ Mutex* make();
+ };
+}
+
+#endif
diff --git a/modules/tm_hard/modinfo.txt b/modules/tm_hard/modinfo.txt
new file mode 100644
index 000000000..d03df5d30
--- /dev/null
+++ b/modules/tm_hard/modinfo.txt
@@ -0,0 +1,24 @@
+realname "Hardware Timer"
+
+define TIMER_HARDWARE
+
+add_file tm_hard.cpp
+add_file tm_hard.h
+
+<cc>
+gcc
+</cc>
+
+<arch>
+# RDTSC: Pentium and up
+i586
+i686
+athlon
+pentium4
+amd64
+
+ppc # PPC timebase register
+ppc64 # PPC timebase register
+alpha # rpcc
+sparc64 # %tick register
+</arch>
diff --git a/modules/tm_hard/tm_hard.cpp b/modules/tm_hard/tm_hard.cpp
new file mode 100644
index 000000000..0005f79c2
--- /dev/null
+++ b/modules/tm_hard/tm_hard.cpp
@@ -0,0 +1,41 @@
+/*************************************************
+* Hardware Timer Source File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#include <botan/tm_hard.h>
+#include <botan/config.h>
+
+namespace Botan {
+
+/*************************************************
+* Get the timestamp *
+*************************************************/
+u64bit Hardware_Timer::clock() const
+ {
+ u64bit rtc = 0;
+
+#if !defined(__GNUC__)
+ #error "This module uses GCC-style inline asm"
+#endif
+
+#if defined(BOTAN_TARGET_ARCH_IS_IA32) || defined(BOTAN_TARGET_ARCH_IS_AMD64)
+ u32bit rtc_low = 0, rtc_high = 0;
+ asm volatile("rdtsc" : "=d" (rtc_high), "=a" (rtc_low));
+ rtc = ((u64bit)rtc_high << 32) | rtc_low;
+#elif defined(BOTAN_TARGET_ARCH_IS_PPC) || defined(BOTAN_TARGET_ARCH_IS_PPC64)
+ u32bit rtc_low = 0, rtc_high = 0;
+ asm volatile("mftbu %0; mftb %1" : "=r" (rtc_high), "=r" (rtc_low));
+ rtc = ((u64bit)rtc_high << 32) | rtc_low;
+#elif defined(BOTAN_TARGET_ARCH_IS_ALPHA)
+ asm volatile("rpcc %0" : "=r" (rtc));
+#elif defined(BOTAN_TARGET_ARCH_IS_SPARC64)
+ asm volatile("rd %%tick, %0" : "=r" (rtc));
+#else
+ #error "Unsure how to access hardware timer on this system"
+#endif
+
+ return rtc;
+ }
+
+}
diff --git a/modules/tm_hard/tm_hard.h b/modules/tm_hard/tm_hard.h
new file mode 100644
index 000000000..017bc5cad
--- /dev/null
+++ b/modules/tm_hard/tm_hard.h
@@ -0,0 +1,24 @@
+/*************************************************
+* Hardware Timer Header File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#ifndef BOTAN_EXT_TIMER_HARDWARE_H__
+#define BOTAN_EXT_TIMER_HARDWARE_H__
+
+#include <botan/timers.h>
+
+namespace Botan {
+
+/*************************************************
+* Hardware Timer *
+*************************************************/
+class Hardware_Timer : public Timer
+ {
+ public:
+ u64bit clock() const;
+ };
+
+}
+
+#endif
diff --git a/modules/tm_posix/modinfo.txt b/modules/tm_posix/modinfo.txt
new file mode 100644
index 000000000..df8d63122
--- /dev/null
+++ b/modules/tm_posix/modinfo.txt
@@ -0,0 +1,19 @@
+realname "POSIX Timer"
+
+define TIMER_POSIX
+
+add_file tm_posix.cpp
+add_file tm_posix.h
+
+<libs>
+linux -> rt
+</libs>
+
+# The *BSDs put clock_gettime in sys/time.h, not time.h like POSIX says
+<os>
+cygwin
+linux
+#freebsd
+#netbsd
+#openbsd
+</os>
diff --git a/modules/tm_posix/tm_posix.cpp b/modules/tm_posix/tm_posix.cpp
new file mode 100644
index 000000000..bec82bc41
--- /dev/null
+++ b/modules/tm_posix/tm_posix.cpp
@@ -0,0 +1,31 @@
+/*************************************************
+* POSIX Timer Source File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#include <botan/tm_posix.h>
+#include <botan/util.h>
+
+#ifndef _POSIX_C_SOURCE
+ #define _POSIX_C_SOURCE 199309
+#endif
+
+#include <time.h>
+
+#ifndef CLOCK_REALTIME
+ #define CLOCK_REALTIME 0
+#endif
+
+namespace Botan {
+
+/*************************************************
+* Get the timestamp *
+*************************************************/
+u64bit POSIX_Timer::clock() const
+ {
+ struct timespec tv;
+ clock_gettime(CLOCK_REALTIME, &tv);
+ return combine_timers(tv.tv_sec, tv.tv_nsec, 1000000000);
+ }
+
+}
diff --git a/modules/tm_posix/tm_posix.h b/modules/tm_posix/tm_posix.h
new file mode 100644
index 000000000..9a921ab3e
--- /dev/null
+++ b/modules/tm_posix/tm_posix.h
@@ -0,0 +1,24 @@
+/*************************************************
+* POSIX Timer Header File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#ifndef BOTAN_EXT_TIMER_POSIX_H__
+#define BOTAN_EXT_TIMER_POSIX_H__
+
+#include <botan/timers.h>
+
+namespace Botan {
+
+/*************************************************
+* POSIX Timer *
+*************************************************/
+class POSIX_Timer : public Timer
+ {
+ public:
+ u64bit clock() const;
+ };
+
+}
+
+#endif
diff --git a/modules/tm_unix/modinfo.txt b/modules/tm_unix/modinfo.txt
new file mode 100644
index 000000000..78400fbc9
--- /dev/null
+++ b/modules/tm_unix/modinfo.txt
@@ -0,0 +1,22 @@
+realname "Unix Timer"
+
+define TIMER_UNIX
+
+add_file tm_unix.cpp
+add_file tm_unix.h
+
+<os>
+aix
+beos
+cygwin
+darwin
+freebsd
+hpux
+irix
+linux
+netbsd
+openbsd
+qnx
+solaris
+tru64
+</os>
diff --git a/modules/tm_unix/tm_unix.cpp b/modules/tm_unix/tm_unix.cpp
new file mode 100644
index 000000000..3cf6928be
--- /dev/null
+++ b/modules/tm_unix/tm_unix.cpp
@@ -0,0 +1,22 @@
+/*************************************************
+* Unix Timer Source File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#include <botan/tm_unix.h>
+#include <botan/util.h>
+#include <sys/time.h>
+
+namespace Botan {
+
+/*************************************************
+* Get the timestamp *
+*************************************************/
+u64bit Unix_Timer::clock() const
+ {
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+ return combine_timers(tv.tv_sec, tv.tv_usec, 1000000);
+ }
+
+}
diff --git a/modules/tm_unix/tm_unix.h b/modules/tm_unix/tm_unix.h
new file mode 100644
index 000000000..2c14cb2d0
--- /dev/null
+++ b/modules/tm_unix/tm_unix.h
@@ -0,0 +1,24 @@
+/*************************************************
+* Unix Timer Header File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#ifndef BOTAN_EXT_TIMER_UNIX_H__
+#define BOTAN_EXT_TIMER_UNIX_H__
+
+#include <botan/timers.h>
+
+namespace Botan {
+
+/*************************************************
+* Unix Timer *
+*************************************************/
+class Unix_Timer : public Timer
+ {
+ public:
+ u64bit clock() const;
+ };
+
+}
+
+#endif
diff --git a/modules/tm_win32/modinfo.txt b/modules/tm_win32/modinfo.txt
new file mode 100644
index 000000000..db9c4d9b8
--- /dev/null
+++ b/modules/tm_win32/modinfo.txt
@@ -0,0 +1,15 @@
+realname "Win32 Timer"
+
+define TIMER_WIN32
+
+add_file tm_win32.cpp
+add_file tm_win32.h
+
+<os>
+cygwin
+windows
+</os>
+
+<libs>
+windows -> user32
+</libs>
diff --git a/modules/tm_win32/tm_win32.cpp b/modules/tm_win32/tm_win32.cpp
new file mode 100644
index 000000000..1f4a33bf4
--- /dev/null
+++ b/modules/tm_win32/tm_win32.cpp
@@ -0,0 +1,21 @@
+/*************************************************
+* Win32 Timer Source File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#include <botan/tm_win32.h>
+#include <windows.h>
+
+namespace Botan {
+
+/*************************************************
+* Get the timestamp *
+*************************************************/
+u64bit Win32_Timer::clock() const
+ {
+ LARGE_INTEGER tv;
+ ::QueryPerformanceCounter(&tv);
+ return tv.QuadPart;
+ }
+
+}
diff --git a/modules/tm_win32/tm_win32.h b/modules/tm_win32/tm_win32.h
new file mode 100644
index 000000000..ec4175d2d
--- /dev/null
+++ b/modules/tm_win32/tm_win32.h
@@ -0,0 +1,24 @@
+/*************************************************
+* Win32 Timer Header File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#ifndef BOTAN_EXT_TIMER_WIN32_H__
+#define BOTAN_EXT_TIMER_WIN32_H__
+
+#include <botan/timers.h>
+
+namespace Botan {
+
+/*************************************************
+* Win32 Timer *
+*************************************************/
+class Win32_Timer : public Timer
+ {
+ public:
+ u64bit clock() const;
+ };
+
+}
+
+#endif