diff options
author | lloyd <[email protected]> | 2006-05-18 18:33:19 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2006-05-18 18:33:19 +0000 |
commit | a2c99d3270eb73ef2db5704fc54356c6b75096f8 (patch) | |
tree | ad3d6c4fcc8dd0f403f8105598943616246fe172 /modules |
Initial checkin1.5.6
Diffstat (limited to 'modules')
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 |