From a6f3801debb5239505ec2c9523a7fec5a9bbb070 Mon Sep 17 00:00:00 2001 From: lloyd Date: Sun, 28 Sep 2008 23:23:51 +0000 Subject: Move allocator code to secalloc/allocators module Move paralle hash construction to par_hash module in hash directory --- include/allocate.h | 35 ----- include/defalloc.h | 39 ------ include/mem_pool.h | 74 ---------- include/par_hash.h | 33 ----- include/secmem.h | 217 ----------------------------- src/def_alg.cpp | 5 +- src/defalloc.cpp | 98 ------------- src/hash/par_hash/modinfo.txt | 10 ++ src/hash/par_hash/par_hash.cpp | 102 ++++++++++++++ src/hash/par_hash/par_hash.h | 33 +++++ src/mem_pool.cpp | 261 ----------------------------------- src/par_hash.cpp | 102 -------------- src/secalloc/allocators/allocate.h | 35 +++++ src/secalloc/allocators/defalloc.cpp | 98 +++++++++++++ src/secalloc/allocators/defalloc.h | 39 ++++++ src/secalloc/allocators/mem_pool.cpp | 261 +++++++++++++++++++++++++++++++++++ src/secalloc/allocators/mem_pool.h | 74 ++++++++++ src/secalloc/allocators/modinfo.txt | 14 ++ src/secalloc/allocators/secmem.h | 217 +++++++++++++++++++++++++++++ 19 files changed, 887 insertions(+), 860 deletions(-) delete mode 100644 include/allocate.h delete mode 100644 include/defalloc.h delete mode 100644 include/mem_pool.h delete mode 100644 include/par_hash.h delete mode 100644 include/secmem.h delete mode 100644 src/defalloc.cpp create mode 100644 src/hash/par_hash/modinfo.txt create mode 100644 src/hash/par_hash/par_hash.cpp create mode 100644 src/hash/par_hash/par_hash.h delete mode 100644 src/mem_pool.cpp delete mode 100644 src/par_hash.cpp create mode 100644 src/secalloc/allocators/allocate.h create mode 100644 src/secalloc/allocators/defalloc.cpp create mode 100644 src/secalloc/allocators/defalloc.h create mode 100644 src/secalloc/allocators/mem_pool.cpp create mode 100644 src/secalloc/allocators/mem_pool.h create mode 100644 src/secalloc/allocators/modinfo.txt create mode 100644 src/secalloc/allocators/secmem.h diff --git a/include/allocate.h b/include/allocate.h deleted file mode 100644 index efbb77291..000000000 --- a/include/allocate.h +++ /dev/null @@ -1,35 +0,0 @@ -/************************************************* -* Allocator Header File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#ifndef BOTAN_ALLOCATOR_H__ -#define BOTAN_ALLOCATOR_H__ - -#include -#include - -namespace Botan { - -/************************************************* -* Allocator Interface * -*************************************************/ -class BOTAN_DLL Allocator - { - public: - static Allocator* get(bool); - - virtual void* allocate(u32bit) = 0; - virtual void deallocate(void*, u32bit) = 0; - - virtual std::string type() const = 0; - - virtual void init() {} - virtual void destroy() {} - - virtual ~Allocator() {} - }; - -} - -#endif diff --git a/include/defalloc.h b/include/defalloc.h deleted file mode 100644 index f162f5c71..000000000 --- a/include/defalloc.h +++ /dev/null @@ -1,39 +0,0 @@ -/************************************************* -* Basic Allocators Header File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#ifndef BOTAN_BASIC_ALLOC_H__ -#define BOTAN_BASIC_ALLOC_H__ - -#include - -namespace Botan { - -/************************************************* -* Malloc Allocator * -*************************************************/ -class BOTAN_DLL Malloc_Allocator : public Allocator - { - public: - void* allocate(u32bit); - void deallocate(void*, u32bit); - - std::string type() const { return "malloc"; } - }; - -/************************************************* -* Locking Allocator * -*************************************************/ -class BOTAN_DLL Locking_Allocator : public Pooling_Allocator - { - public: - std::string type() const { return "locking"; } - private: - void* alloc_block(u32bit); - void dealloc_block(void*, u32bit); - }; - -} - -#endif diff --git a/include/mem_pool.h b/include/mem_pool.h deleted file mode 100644 index 3d28034e7..000000000 --- a/include/mem_pool.h +++ /dev/null @@ -1,74 +0,0 @@ -/************************************************* -* Pooling Allocator Header File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#ifndef BOTAN_POOLING_ALLOCATOR_H__ -#define BOTAN_POOLING_ALLOCATOR_H__ - -#include -#include -#include -#include -#include - -namespace Botan { - -/************************************************* -* Pooling Allocator * -*************************************************/ -class BOTAN_DLL Pooling_Allocator : public Allocator - { - public: - void* allocate(u32bit); - void deallocate(void*, u32bit); - - void destroy(); - - Pooling_Allocator(); - ~Pooling_Allocator(); - private: - void get_more_core(u32bit); - byte* allocate_blocks(u32bit); - - virtual void* alloc_block(u32bit) = 0; - virtual void dealloc_block(void*, u32bit) = 0; - - class BOTAN_DLL Memory_Block - { - public: - Memory_Block(void*); - - static u32bit bitmap_size() { return BITMAP_SIZE; } - static u32bit block_size() { return BLOCK_SIZE; } - - bool contains(void*, u32bit) const throw(); - byte* alloc(u32bit) throw(); - void free(void*, u32bit) throw(); - - bool operator<(const Memory_Block& other) const - { - if(buffer < other.buffer && other.buffer < buffer_end) - return false; - return (buffer < other.buffer); - } - private: - typedef u64bit bitmap_type; - static const u32bit BITMAP_SIZE = 8 * sizeof(bitmap_type); - static const u32bit BLOCK_SIZE = 64; - - bitmap_type bitmap; - byte* buffer, *buffer_end; - }; - - static const u32bit PREF_SIZE = BOTAN_MEM_POOL_CHUNK_SIZE; - - std::vector blocks; - std::vector::iterator last_used; - std::vector > allocated; - Mutex* mutex; - }; - -} - -#endif diff --git a/include/par_hash.h b/include/par_hash.h deleted file mode 100644 index 844a6fb50..000000000 --- a/include/par_hash.h +++ /dev/null @@ -1,33 +0,0 @@ -/************************************************* -* Parallel Header File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#ifndef BOTAN_PAR_HASH_H__ -#define BOTAN_PAR_HASH_H__ - -#include -#include - -namespace Botan { - -/************************************************* -* Parallel * -*************************************************/ -class BOTAN_DLL Parallel : public HashFunction - { - public: - void clear() throw(); - std::string name() const; - HashFunction* clone() const; - Parallel(const std::vector&); - ~Parallel(); - private: - void add_data(const byte[], u32bit); - void final_result(byte[]); - std::vector hashes; - }; - -} - -#endif diff --git a/include/secmem.h b/include/secmem.h deleted file mode 100644 index 37adf7f42..000000000 --- a/include/secmem.h +++ /dev/null @@ -1,217 +0,0 @@ -/************************************************* -* Secure Memory Buffers Header File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#ifndef BOTAN_SECURE_MEMORY_BUFFERS_H__ -#define BOTAN_SECURE_MEMORY_BUFFERS_H__ - -#include -#include - -namespace Botan { - -/************************************************* -* Variable Length Memory Buffer * -*************************************************/ -template -class MemoryRegion - { - public: - u32bit size() const { return used; } - u32bit is_empty() const { return (used == 0); } - u32bit has_items() const { return (used != 0); } - - operator T* () { return buf; } - operator const T* () const { return buf; } - - T* begin() { return buf; } - const T* begin() const { return buf; } - - T* end() { return (buf + size()); } - const T* end() const { return (buf + size()); } - - bool operator==(const MemoryRegion& other) const - { - return (size() == other.size() && - same_mem(buf, other.buf, size())); - } - - bool operator<(const MemoryRegion&) const; - - bool operator!=(const MemoryRegion& in) const - { return (!(*this == in)); } - MemoryRegion& operator=(const MemoryRegion& in) - { if(this != &in) set(in); return (*this); } - - void copy(const T in[], u32bit n) - { copy(0, in, n); } - void copy(u32bit off, const T in[], u32bit n) - { copy_mem(buf + off, in, (n > size() - off) ? (size() - off) : n); } - - void set(const T in[], u32bit n) { create(n); copy(in, n); } - void set(const MemoryRegion& in) { set(in.begin(), in.size()); } - - void append(const T data[], u32bit n) - { grow_to(size()+n); copy(size() - n, data, n); } - void append(T x) { append(&x, 1); } - void append(const MemoryRegion& x) { append(x.begin(), x.size()); } - - void clear() { clear_mem(buf, allocated); } - void destroy() { create(0); } - - void create(u32bit); - void grow_to(u32bit); - void swap(MemoryRegion&); - - ~MemoryRegion() { deallocate(buf, allocated); } - protected: - MemoryRegion() { buf = 0; alloc = 0; used = allocated = 0; } - MemoryRegion(const MemoryRegion& other) - { - buf = 0; - used = allocated = 0; - alloc = other.alloc; - set(other.buf, other.used); - } - - void init(bool locking, u32bit length = 0) - { alloc = Allocator::get(locking); create(length); } - private: - T* allocate(u32bit n) - { - return static_cast(alloc->allocate(sizeof(T)*n)); - } - - void deallocate(T* p, u32bit n) - { alloc->deallocate(p, sizeof(T)*n); } - - T* buf; - u32bit used; - u32bit allocated; - Allocator* alloc; - }; - -/************************************************* -* Create a new buffer * -*************************************************/ -template -void MemoryRegion::create(u32bit n) - { - if(n <= allocated) { clear(); used = n; return; } - deallocate(buf, allocated); - buf = allocate(n); - allocated = used = n; - } - -/************************************************* -* Increase the size of the buffer * -*************************************************/ -template -void MemoryRegion::grow_to(u32bit n) - { - if(n > used && n <= allocated) - { - clear_mem(buf + used, n - used); - used = n; - return; - } - else if(n > allocated) - { - T* new_buf = allocate(n); - copy_mem(new_buf, buf, used); - deallocate(buf, allocated); - buf = new_buf; - allocated = used = n; - } - } - -/************************************************* -* Compare this buffer with another one * -*************************************************/ -template -bool MemoryRegion::operator<(const MemoryRegion& in) const - { - if(size() < in.size()) return true; - if(size() > in.size()) return false; - - for(u32bit j = 0; j != size(); j++) - { - if(buf[j] < in[j]) return true; - if(buf[j] > in[j]) return false; - } - - return false; - } - -/************************************************* -* Swap this buffer with another one * -*************************************************/ -template -void MemoryRegion::swap(MemoryRegion& x) - { - std::swap(buf, x.buf); - std::swap(used, x.used); - std::swap(allocated, x.allocated); - std::swap(alloc, x.alloc); - } - -/************************************************* -* Unlocked Variable Length Buffer * -*************************************************/ -template -class MemoryVector : public MemoryRegion - { - public: - MemoryVector& operator=(const MemoryRegion& in) - { if(this != &in) set(in); return (*this); } - - MemoryVector(u32bit n = 0) { MemoryRegion::init(false, n); } - MemoryVector(const T in[], u32bit n) - { MemoryRegion::init(false); set(in, n); } - MemoryVector(const MemoryRegion& in) - { MemoryRegion::init(false); set(in); } - MemoryVector(const MemoryRegion& in1, const MemoryRegion& in2) - { MemoryRegion::init(false); set(in1); append(in2); } - }; - -/************************************************* -* Locked Variable Length Buffer * -*************************************************/ -template -class SecureVector : public MemoryRegion - { - public: - SecureVector& operator=(const MemoryRegion& in) - { if(this != &in) set(in); return (*this); } - - SecureVector(u32bit n = 0) { MemoryRegion::init(true, n); } - SecureVector(const T in[], u32bit n) - { MemoryRegion::init(true); set(in, n); } - SecureVector(const MemoryRegion& in) - { MemoryRegion::init(true); set(in); } - SecureVector(const MemoryRegion& in1, const MemoryRegion& in2) - { MemoryRegion::init(true); set(in1); append(in2); } - }; - -/************************************************* -* Locked Fixed Length Buffer * -*************************************************/ -template -class SecureBuffer : public MemoryRegion - { - public: - SecureBuffer& operator=(const SecureBuffer& in) - { if(this != &in) set(in); return (*this); } - - SecureBuffer() { MemoryRegion::init(true, L); } - SecureBuffer(const T in[], u32bit n) - { MemoryRegion::init(true, L); copy(in, n); } - private: - SecureBuffer& operator=(const MemoryRegion& in) - { if(this != &in) set(in); return (*this); } - }; - -} - -#endif diff --git a/src/def_alg.cpp b/src/def_alg.cpp index 7bcc84378..80d3a771f 100644 --- a/src/def_alg.cpp +++ b/src/def_alg.cpp @@ -7,7 +7,6 @@ #include #include -#include #include #if defined(BOTAN_HAS_AES) @@ -176,6 +175,10 @@ #include #endif +#if defined(BOTAN_HAS_PARALLEL_HASH) + #include +#endif + #if defined(BOTAN_HAS_CBC_MAC) #include #endif diff --git a/src/defalloc.cpp b/src/defalloc.cpp deleted file mode 100644 index 5fb8e1447..000000000 --- a/src/defalloc.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/************************************************* -* Basic Allocators Source File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#include -#include -#include -#include -#include - -namespace Botan { - -namespace { - -/************************************************* -* Perform Memory Allocation * -*************************************************/ -void* do_malloc(u32bit n, bool do_lock) - { - void* ptr = std::malloc(n); - - if(!ptr) - return 0; - - if(do_lock) - lock_mem(ptr, n); - - std::memset(ptr, 0, n); - return ptr; - } - -/************************************************* -* Perform Memory Deallocation * -*************************************************/ -void do_free(void* ptr, u32bit n, bool do_lock) - { - if(!ptr) - return; - - std::memset(ptr, 0, n); - if(do_lock) - unlock_mem(ptr, n); - - std::free(ptr); - } - -} - -/************************************************* -* Malloc_Allocator's Allocation * -*************************************************/ -void* Malloc_Allocator::allocate(u32bit n) - { - return do_malloc(n, false); - } - -/************************************************* -* Malloc_Allocator's Deallocation * -*************************************************/ -void Malloc_Allocator::deallocate(void* ptr, u32bit n) - { - do_free(ptr, n, false); - } - -/************************************************* -* Locking_Allocator's Allocation * -*************************************************/ -void* Locking_Allocator::alloc_block(u32bit n) - { - return do_malloc(n, true); - } - -/************************************************* -* Locking_Allocator's Deallocation * -*************************************************/ -void Locking_Allocator::dealloc_block(void* ptr, u32bit n) - { - do_free(ptr, n, true); - } - -/************************************************* -* Get an allocator * -*************************************************/ -Allocator* Allocator::get(bool locking) - { - std::string type = ""; - if(!locking) - type = "malloc"; - - Allocator* alloc = global_state().get_allocator(type); - if(alloc) - return alloc; - - throw Exception("Couldn't find an allocator to use in get_allocator"); - } - -} diff --git a/src/hash/par_hash/modinfo.txt b/src/hash/par_hash/modinfo.txt new file mode 100644 index 000000000..45716aac8 --- /dev/null +++ b/src/hash/par_hash/modinfo.txt @@ -0,0 +1,10 @@ +realname "Parallel Hash" + +define PARALLEL_HASH + +load_on auto + + +par_hash.cpp +par_hash.h + diff --git a/src/hash/par_hash/par_hash.cpp b/src/hash/par_hash/par_hash.cpp new file mode 100644 index 000000000..12786523f --- /dev/null +++ b/src/hash/par_hash/par_hash.cpp @@ -0,0 +1,102 @@ +/************************************************* +* Parallel Source File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#include +#include + +namespace Botan { + +namespace { + +/************************************************* +* Return the sum of the hash sizes * +*************************************************/ +u32bit sum_of_hash_lengths(const std::vector& names) + { + u32bit sum = 0; + for(u32bit j = 0; j != names.size(); ++j) + sum += output_length_of(names[j]); + return sum; + } + +} + +/************************************************* +* Update the hash * +*************************************************/ +void Parallel::add_data(const byte input[], u32bit length) + { + for(u32bit j = 0; j != hashes.size(); ++j) + hashes[j]->update(input, length); + } + +/************************************************* +* Finalize the hash * +*************************************************/ +void Parallel::final_result(byte hash[]) + { + u32bit offset = 0; + for(u32bit j = 0; j != hashes.size(); ++j) + { + hashes[j]->final(hash + offset); + offset += hashes[j]->OUTPUT_LENGTH; + } + } + +/************************************************* +* Return the name of this type * +*************************************************/ +std::string Parallel::name() const + { + std::string hash_names; + for(u32bit j = 0; j != hashes.size(); ++j) + { + if(j) + hash_names += ','; + hash_names += hashes[j]->name(); + } + return "Parallel(" + hash_names + ")"; + } + +/************************************************* +* Return a clone of this object * +*************************************************/ +HashFunction* Parallel::clone() const + { + std::vector names; + for(u32bit j = 0; j != hashes.size(); ++j) + names.push_back(hashes[j]->name()); + return new Parallel(names); + } + +/************************************************* +* Clear memory of sensitive data * +*************************************************/ +void Parallel::clear() throw() + { + for(u32bit j = 0; j != hashes.size(); ++j) + hashes[j]->clear(); + } + +/************************************************* +* Parallel Constructor * +*************************************************/ +Parallel::Parallel(const std::vector& names) : + HashFunction(sum_of_hash_lengths(names)) + { + for(u32bit j = 0; j != names.size(); ++j) + hashes.push_back(get_hash(names[j])); + } + +/************************************************* +* Parallel Destructor * +*************************************************/ +Parallel::~Parallel() + { + for(u32bit j = 0; j != hashes.size(); ++j) + delete hashes[j]; + } + +} diff --git a/src/hash/par_hash/par_hash.h b/src/hash/par_hash/par_hash.h new file mode 100644 index 000000000..844a6fb50 --- /dev/null +++ b/src/hash/par_hash/par_hash.h @@ -0,0 +1,33 @@ +/************************************************* +* Parallel Header File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#ifndef BOTAN_PAR_HASH_H__ +#define BOTAN_PAR_HASH_H__ + +#include +#include + +namespace Botan { + +/************************************************* +* Parallel * +*************************************************/ +class BOTAN_DLL Parallel : public HashFunction + { + public: + void clear() throw(); + std::string name() const; + HashFunction* clone() const; + Parallel(const std::vector&); + ~Parallel(); + private: + void add_data(const byte[], u32bit); + void final_result(byte[]); + std::vector hashes; + }; + +} + +#endif diff --git a/src/mem_pool.cpp b/src/mem_pool.cpp deleted file mode 100644 index 74d09d5df..000000000 --- a/src/mem_pool.cpp +++ /dev/null @@ -1,261 +0,0 @@ -/************************************************* -* Pooling Allocator Source File * -* (C) 1999-2008 Jack Lloyd * -* 2005 Matthew Gregan * -* 2005-2006 Matt Johnston * -*************************************************/ - -#include -#include -#include -#include -#include - -namespace Botan { - -namespace { - -/************************************************* -* Memory Allocation Exception * -*************************************************/ -struct Memory_Exhaustion : public std::bad_alloc - { - const char* what() - { return "Ran out of memory, allocation failed"; } - }; - -} - -/************************************************* -* Memory_Block Constructor * -*************************************************/ -Pooling_Allocator::Memory_Block::Memory_Block(void* buf) - { - buffer = static_cast(buf); - bitmap = 0; - buffer_end = buffer + (BLOCK_SIZE * BITMAP_SIZE); - } - -/************************************************* -* See if ptr is contained by this block * -*************************************************/ -bool Pooling_Allocator::Memory_Block::contains(void* ptr, - u32bit length) const throw() - { - return ((buffer <= ptr) && - (buffer_end >= static_cast(ptr) + length * BLOCK_SIZE)); - } - -/************************************************* -* Allocate some memory, if possible * -*************************************************/ -byte* Pooling_Allocator::Memory_Block::alloc(u32bit n) throw() - { - if(n == 0 || n > BITMAP_SIZE) - return 0; - - if(n == BITMAP_SIZE) - { - if(bitmap) - return 0; - else - { - bitmap = ~bitmap; - return buffer; - } - } - - bitmap_type mask = (static_cast(1) << n) - 1; - u32bit offset = 0; - - while(bitmap & mask) - { - mask <<= 1; - ++offset; - - if((bitmap & mask) == 0) - break; - if(mask >> 63) - break; - } - - if(bitmap & mask) - return 0; - - bitmap |= mask; - return buffer + offset * BLOCK_SIZE; - } - -/************************************************* -* Mark this memory as free, if we own it * -*************************************************/ -void Pooling_Allocator::Memory_Block::free(void* ptr, u32bit blocks) throw() - { - clear_mem(static_cast(ptr), blocks * BLOCK_SIZE); - - const u32bit offset = (static_cast(ptr) - buffer) / BLOCK_SIZE; - - if(offset == 0 && blocks == BITMAP_SIZE) - bitmap = ~bitmap; - else - { - for(u32bit j = 0; j != blocks; ++j) - bitmap &= ~(static_cast(1) << (j+offset)); - } - } - -/************************************************* -* Pooling_Allocator Constructor * -*************************************************/ -Pooling_Allocator::Pooling_Allocator() - { - mutex = global_state().get_mutex(); - last_used = blocks.begin(); - } - -/************************************************* -* Pooling_Allocator Destructor * -*************************************************/ -Pooling_Allocator::~Pooling_Allocator() - { - delete mutex; - if(blocks.size()) - throw Invalid_State("Pooling_Allocator: Never released memory"); - } - -/************************************************* -* Free all remaining memory * -*************************************************/ -void Pooling_Allocator::destroy() - { - Mutex_Holder lock(mutex); - - blocks.clear(); - - for(u32bit j = 0; j != allocated.size(); ++j) - dealloc_block(allocated[j].first, allocated[j].second); - allocated.clear(); - } - -/************************************************* -* Allocation * -*************************************************/ -void* Pooling_Allocator::allocate(u32bit n) - { - const u32bit BITMAP_SIZE = Memory_Block::bitmap_size(); - const u32bit BLOCK_SIZE = Memory_Block::block_size(); - - Mutex_Holder lock(mutex); - - if(n <= BITMAP_SIZE * BLOCK_SIZE) - { - const u32bit block_no = round_up(n, BLOCK_SIZE) / BLOCK_SIZE; - - byte* mem = allocate_blocks(block_no); - if(mem) - return mem; - - get_more_core(PREF_SIZE); - - mem = allocate_blocks(block_no); - if(mem) - return mem; - - throw Memory_Exhaustion(); - } - - void* new_buf = alloc_block(n); - if(new_buf) - return new_buf; - - throw Memory_Exhaustion(); - } - -/************************************************* -* Deallocation * -*************************************************/ -void Pooling_Allocator::deallocate(void* ptr, u32bit n) - { - const u32bit BITMAP_SIZE = Memory_Block::bitmap_size(); - const u32bit BLOCK_SIZE = Memory_Block::block_size(); - - if(ptr == 0 && n == 0) - return; - - Mutex_Holder lock(mutex); - - if(n > BITMAP_SIZE * BLOCK_SIZE) - dealloc_block(ptr, n); - else - { - const u32bit block_no = round_up(n, BLOCK_SIZE) / BLOCK_SIZE; - - std::vector::iterator i = - std::lower_bound(blocks.begin(), blocks.end(), Memory_Block(ptr)); - - if(i == blocks.end() || !i->contains(ptr, block_no)) - throw Invalid_State("Pointer released to the wrong allocator"); - - i->free(ptr, block_no); - } - } - -/************************************************* -* Try to get some memory from an existing block * -*************************************************/ -byte* Pooling_Allocator::allocate_blocks(u32bit n) - { - if(blocks.empty()) - return 0; - - std::vector::iterator i = last_used; - - do - { - byte* mem = i->alloc(n); - if(mem) - { - last_used = i; - return mem; - } - - ++i; - if(i == blocks.end()) - i = blocks.begin(); - } - while(i != last_used); - - return 0; - } - -/************************************************* -* Allocate more memory for the pool * -*************************************************/ -void Pooling_Allocator::get_more_core(u32bit in_bytes) - { - const u32bit BITMAP_SIZE = Memory_Block::bitmap_size(); - const u32bit BLOCK_SIZE = Memory_Block::block_size(); - - const u32bit TOTAL_BLOCK_SIZE = BLOCK_SIZE * BITMAP_SIZE; - - const u32bit in_blocks = round_up(in_bytes, BLOCK_SIZE) / TOTAL_BLOCK_SIZE; - const u32bit to_allocate = in_blocks * TOTAL_BLOCK_SIZE; - - void* ptr = alloc_block(to_allocate); - if(ptr == 0) - throw Memory_Exhaustion(); - - allocated.push_back(std::make_pair(ptr, to_allocate)); - - for(u32bit j = 0; j != in_blocks; ++j) - { - byte* byte_ptr = static_cast(ptr); - blocks.push_back(Memory_Block(byte_ptr + j * TOTAL_BLOCK_SIZE)); - } - - std::sort(blocks.begin(), blocks.end()); - last_used = std::lower_bound(blocks.begin(), blocks.end(), - Memory_Block(ptr)); - } - -} diff --git a/src/par_hash.cpp b/src/par_hash.cpp deleted file mode 100644 index 12786523f..000000000 --- a/src/par_hash.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/************************************************* -* Parallel Source File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#include -#include - -namespace Botan { - -namespace { - -/************************************************* -* Return the sum of the hash sizes * -*************************************************/ -u32bit sum_of_hash_lengths(const std::vector& names) - { - u32bit sum = 0; - for(u32bit j = 0; j != names.size(); ++j) - sum += output_length_of(names[j]); - return sum; - } - -} - -/************************************************* -* Update the hash * -*************************************************/ -void Parallel::add_data(const byte input[], u32bit length) - { - for(u32bit j = 0; j != hashes.size(); ++j) - hashes[j]->update(input, length); - } - -/************************************************* -* Finalize the hash * -*************************************************/ -void Parallel::final_result(byte hash[]) - { - u32bit offset = 0; - for(u32bit j = 0; j != hashes.size(); ++j) - { - hashes[j]->final(hash + offset); - offset += hashes[j]->OUTPUT_LENGTH; - } - } - -/************************************************* -* Return the name of this type * -*************************************************/ -std::string Parallel::name() const - { - std::string hash_names; - for(u32bit j = 0; j != hashes.size(); ++j) - { - if(j) - hash_names += ','; - hash_names += hashes[j]->name(); - } - return "Parallel(" + hash_names + ")"; - } - -/************************************************* -* Return a clone of this object * -*************************************************/ -HashFunction* Parallel::clone() const - { - std::vector names; - for(u32bit j = 0; j != hashes.size(); ++j) - names.push_back(hashes[j]->name()); - return new Parallel(names); - } - -/************************************************* -* Clear memory of sensitive data * -*************************************************/ -void Parallel::clear() throw() - { - for(u32bit j = 0; j != hashes.size(); ++j) - hashes[j]->clear(); - } - -/************************************************* -* Parallel Constructor * -*************************************************/ -Parallel::Parallel(const std::vector& names) : - HashFunction(sum_of_hash_lengths(names)) - { - for(u32bit j = 0; j != names.size(); ++j) - hashes.push_back(get_hash(names[j])); - } - -/************************************************* -* Parallel Destructor * -*************************************************/ -Parallel::~Parallel() - { - for(u32bit j = 0; j != hashes.size(); ++j) - delete hashes[j]; - } - -} diff --git a/src/secalloc/allocators/allocate.h b/src/secalloc/allocators/allocate.h new file mode 100644 index 000000000..efbb77291 --- /dev/null +++ b/src/secalloc/allocators/allocate.h @@ -0,0 +1,35 @@ +/************************************************* +* Allocator Header File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#ifndef BOTAN_ALLOCATOR_H__ +#define BOTAN_ALLOCATOR_H__ + +#include +#include + +namespace Botan { + +/************************************************* +* Allocator Interface * +*************************************************/ +class BOTAN_DLL Allocator + { + public: + static Allocator* get(bool); + + virtual void* allocate(u32bit) = 0; + virtual void deallocate(void*, u32bit) = 0; + + virtual std::string type() const = 0; + + virtual void init() {} + virtual void destroy() {} + + virtual ~Allocator() {} + }; + +} + +#endif diff --git a/src/secalloc/allocators/defalloc.cpp b/src/secalloc/allocators/defalloc.cpp new file mode 100644 index 000000000..5fb8e1447 --- /dev/null +++ b/src/secalloc/allocators/defalloc.cpp @@ -0,0 +1,98 @@ +/************************************************* +* Basic Allocators Source File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#include +#include +#include +#include +#include + +namespace Botan { + +namespace { + +/************************************************* +* Perform Memory Allocation * +*************************************************/ +void* do_malloc(u32bit n, bool do_lock) + { + void* ptr = std::malloc(n); + + if(!ptr) + return 0; + + if(do_lock) + lock_mem(ptr, n); + + std::memset(ptr, 0, n); + return ptr; + } + +/************************************************* +* Perform Memory Deallocation * +*************************************************/ +void do_free(void* ptr, u32bit n, bool do_lock) + { + if(!ptr) + return; + + std::memset(ptr, 0, n); + if(do_lock) + unlock_mem(ptr, n); + + std::free(ptr); + } + +} + +/************************************************* +* Malloc_Allocator's Allocation * +*************************************************/ +void* Malloc_Allocator::allocate(u32bit n) + { + return do_malloc(n, false); + } + +/************************************************* +* Malloc_Allocator's Deallocation * +*************************************************/ +void Malloc_Allocator::deallocate(void* ptr, u32bit n) + { + do_free(ptr, n, false); + } + +/************************************************* +* Locking_Allocator's Allocation * +*************************************************/ +void* Locking_Allocator::alloc_block(u32bit n) + { + return do_malloc(n, true); + } + +/************************************************* +* Locking_Allocator's Deallocation * +*************************************************/ +void Locking_Allocator::dealloc_block(void* ptr, u32bit n) + { + do_free(ptr, n, true); + } + +/************************************************* +* Get an allocator * +*************************************************/ +Allocator* Allocator::get(bool locking) + { + std::string type = ""; + if(!locking) + type = "malloc"; + + Allocator* alloc = global_state().get_allocator(type); + if(alloc) + return alloc; + + throw Exception("Couldn't find an allocator to use in get_allocator"); + } + +} diff --git a/src/secalloc/allocators/defalloc.h b/src/secalloc/allocators/defalloc.h new file mode 100644 index 000000000..f162f5c71 --- /dev/null +++ b/src/secalloc/allocators/defalloc.h @@ -0,0 +1,39 @@ +/************************************************* +* Basic Allocators Header File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#ifndef BOTAN_BASIC_ALLOC_H__ +#define BOTAN_BASIC_ALLOC_H__ + +#include + +namespace Botan { + +/************************************************* +* Malloc Allocator * +*************************************************/ +class BOTAN_DLL Malloc_Allocator : public Allocator + { + public: + void* allocate(u32bit); + void deallocate(void*, u32bit); + + std::string type() const { return "malloc"; } + }; + +/************************************************* +* Locking Allocator * +*************************************************/ +class BOTAN_DLL Locking_Allocator : public Pooling_Allocator + { + public: + std::string type() const { return "locking"; } + private: + void* alloc_block(u32bit); + void dealloc_block(void*, u32bit); + }; + +} + +#endif diff --git a/src/secalloc/allocators/mem_pool.cpp b/src/secalloc/allocators/mem_pool.cpp new file mode 100644 index 000000000..74d09d5df --- /dev/null +++ b/src/secalloc/allocators/mem_pool.cpp @@ -0,0 +1,261 @@ +/************************************************* +* Pooling Allocator Source File * +* (C) 1999-2008 Jack Lloyd * +* 2005 Matthew Gregan * +* 2005-2006 Matt Johnston * +*************************************************/ + +#include +#include +#include +#include +#include + +namespace Botan { + +namespace { + +/************************************************* +* Memory Allocation Exception * +*************************************************/ +struct Memory_Exhaustion : public std::bad_alloc + { + const char* what() + { return "Ran out of memory, allocation failed"; } + }; + +} + +/************************************************* +* Memory_Block Constructor * +*************************************************/ +Pooling_Allocator::Memory_Block::Memory_Block(void* buf) + { + buffer = static_cast(buf); + bitmap = 0; + buffer_end = buffer + (BLOCK_SIZE * BITMAP_SIZE); + } + +/************************************************* +* See if ptr is contained by this block * +*************************************************/ +bool Pooling_Allocator::Memory_Block::contains(void* ptr, + u32bit length) const throw() + { + return ((buffer <= ptr) && + (buffer_end >= static_cast(ptr) + length * BLOCK_SIZE)); + } + +/************************************************* +* Allocate some memory, if possible * +*************************************************/ +byte* Pooling_Allocator::Memory_Block::alloc(u32bit n) throw() + { + if(n == 0 || n > BITMAP_SIZE) + return 0; + + if(n == BITMAP_SIZE) + { + if(bitmap) + return 0; + else + { + bitmap = ~bitmap; + return buffer; + } + } + + bitmap_type mask = (static_cast(1) << n) - 1; + u32bit offset = 0; + + while(bitmap & mask) + { + mask <<= 1; + ++offset; + + if((bitmap & mask) == 0) + break; + if(mask >> 63) + break; + } + + if(bitmap & mask) + return 0; + + bitmap |= mask; + return buffer + offset * BLOCK_SIZE; + } + +/************************************************* +* Mark this memory as free, if we own it * +*************************************************/ +void Pooling_Allocator::Memory_Block::free(void* ptr, u32bit blocks) throw() + { + clear_mem(static_cast(ptr), blocks * BLOCK_SIZE); + + const u32bit offset = (static_cast(ptr) - buffer) / BLOCK_SIZE; + + if(offset == 0 && blocks == BITMAP_SIZE) + bitmap = ~bitmap; + else + { + for(u32bit j = 0; j != blocks; ++j) + bitmap &= ~(static_cast(1) << (j+offset)); + } + } + +/************************************************* +* Pooling_Allocator Constructor * +*************************************************/ +Pooling_Allocator::Pooling_Allocator() + { + mutex = global_state().get_mutex(); + last_used = blocks.begin(); + } + +/************************************************* +* Pooling_Allocator Destructor * +*************************************************/ +Pooling_Allocator::~Pooling_Allocator() + { + delete mutex; + if(blocks.size()) + throw Invalid_State("Pooling_Allocator: Never released memory"); + } + +/************************************************* +* Free all remaining memory * +*************************************************/ +void Pooling_Allocator::destroy() + { + Mutex_Holder lock(mutex); + + blocks.clear(); + + for(u32bit j = 0; j != allocated.size(); ++j) + dealloc_block(allocated[j].first, allocated[j].second); + allocated.clear(); + } + +/************************************************* +* Allocation * +*************************************************/ +void* Pooling_Allocator::allocate(u32bit n) + { + const u32bit BITMAP_SIZE = Memory_Block::bitmap_size(); + const u32bit BLOCK_SIZE = Memory_Block::block_size(); + + Mutex_Holder lock(mutex); + + if(n <= BITMAP_SIZE * BLOCK_SIZE) + { + const u32bit block_no = round_up(n, BLOCK_SIZE) / BLOCK_SIZE; + + byte* mem = allocate_blocks(block_no); + if(mem) + return mem; + + get_more_core(PREF_SIZE); + + mem = allocate_blocks(block_no); + if(mem) + return mem; + + throw Memory_Exhaustion(); + } + + void* new_buf = alloc_block(n); + if(new_buf) + return new_buf; + + throw Memory_Exhaustion(); + } + +/************************************************* +* Deallocation * +*************************************************/ +void Pooling_Allocator::deallocate(void* ptr, u32bit n) + { + const u32bit BITMAP_SIZE = Memory_Block::bitmap_size(); + const u32bit BLOCK_SIZE = Memory_Block::block_size(); + + if(ptr == 0 && n == 0) + return; + + Mutex_Holder lock(mutex); + + if(n > BITMAP_SIZE * BLOCK_SIZE) + dealloc_block(ptr, n); + else + { + const u32bit block_no = round_up(n, BLOCK_SIZE) / BLOCK_SIZE; + + std::vector::iterator i = + std::lower_bound(blocks.begin(), blocks.end(), Memory_Block(ptr)); + + if(i == blocks.end() || !i->contains(ptr, block_no)) + throw Invalid_State("Pointer released to the wrong allocator"); + + i->free(ptr, block_no); + } + } + +/************************************************* +* Try to get some memory from an existing block * +*************************************************/ +byte* Pooling_Allocator::allocate_blocks(u32bit n) + { + if(blocks.empty()) + return 0; + + std::vector::iterator i = last_used; + + do + { + byte* mem = i->alloc(n); + if(mem) + { + last_used = i; + return mem; + } + + ++i; + if(i == blocks.end()) + i = blocks.begin(); + } + while(i != last_used); + + return 0; + } + +/************************************************* +* Allocate more memory for the pool * +*************************************************/ +void Pooling_Allocator::get_more_core(u32bit in_bytes) + { + const u32bit BITMAP_SIZE = Memory_Block::bitmap_size(); + const u32bit BLOCK_SIZE = Memory_Block::block_size(); + + const u32bit TOTAL_BLOCK_SIZE = BLOCK_SIZE * BITMAP_SIZE; + + const u32bit in_blocks = round_up(in_bytes, BLOCK_SIZE) / TOTAL_BLOCK_SIZE; + const u32bit to_allocate = in_blocks * TOTAL_BLOCK_SIZE; + + void* ptr = alloc_block(to_allocate); + if(ptr == 0) + throw Memory_Exhaustion(); + + allocated.push_back(std::make_pair(ptr, to_allocate)); + + for(u32bit j = 0; j != in_blocks; ++j) + { + byte* byte_ptr = static_cast(ptr); + blocks.push_back(Memory_Block(byte_ptr + j * TOTAL_BLOCK_SIZE)); + } + + std::sort(blocks.begin(), blocks.end()); + last_used = std::lower_bound(blocks.begin(), blocks.end(), + Memory_Block(ptr)); + } + +} diff --git a/src/secalloc/allocators/mem_pool.h b/src/secalloc/allocators/mem_pool.h new file mode 100644 index 000000000..3d28034e7 --- /dev/null +++ b/src/secalloc/allocators/mem_pool.h @@ -0,0 +1,74 @@ +/************************************************* +* Pooling Allocator Header File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#ifndef BOTAN_POOLING_ALLOCATOR_H__ +#define BOTAN_POOLING_ALLOCATOR_H__ + +#include +#include +#include +#include +#include + +namespace Botan { + +/************************************************* +* Pooling Allocator * +*************************************************/ +class BOTAN_DLL Pooling_Allocator : public Allocator + { + public: + void* allocate(u32bit); + void deallocate(void*, u32bit); + + void destroy(); + + Pooling_Allocator(); + ~Pooling_Allocator(); + private: + void get_more_core(u32bit); + byte* allocate_blocks(u32bit); + + virtual void* alloc_block(u32bit) = 0; + virtual void dealloc_block(void*, u32bit) = 0; + + class BOTAN_DLL Memory_Block + { + public: + Memory_Block(void*); + + static u32bit bitmap_size() { return BITMAP_SIZE; } + static u32bit block_size() { return BLOCK_SIZE; } + + bool contains(void*, u32bit) const throw(); + byte* alloc(u32bit) throw(); + void free(void*, u32bit) throw(); + + bool operator<(const Memory_Block& other) const + { + if(buffer < other.buffer && other.buffer < buffer_end) + return false; + return (buffer < other.buffer); + } + private: + typedef u64bit bitmap_type; + static const u32bit BITMAP_SIZE = 8 * sizeof(bitmap_type); + static const u32bit BLOCK_SIZE = 64; + + bitmap_type bitmap; + byte* buffer, *buffer_end; + }; + + static const u32bit PREF_SIZE = BOTAN_MEM_POOL_CHUNK_SIZE; + + std::vector blocks; + std::vector::iterator last_used; + std::vector > allocated; + Mutex* mutex; + }; + +} + +#endif diff --git a/src/secalloc/allocators/modinfo.txt b/src/secalloc/allocators/modinfo.txt new file mode 100644 index 000000000..e2d8d2a16 --- /dev/null +++ b/src/secalloc/allocators/modinfo.txt @@ -0,0 +1,14 @@ +realname "Secure Memory Allocation" + +load_on auto + +define SECMEM + + +defalloc.cpp +mem_pool.cpp +allocate.h +defalloc.h +mem_pool.h +secmem.h + diff --git a/src/secalloc/allocators/secmem.h b/src/secalloc/allocators/secmem.h new file mode 100644 index 000000000..37adf7f42 --- /dev/null +++ b/src/secalloc/allocators/secmem.h @@ -0,0 +1,217 @@ +/************************************************* +* Secure Memory Buffers Header File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#ifndef BOTAN_SECURE_MEMORY_BUFFERS_H__ +#define BOTAN_SECURE_MEMORY_BUFFERS_H__ + +#include +#include + +namespace Botan { + +/************************************************* +* Variable Length Memory Buffer * +*************************************************/ +template +class MemoryRegion + { + public: + u32bit size() const { return used; } + u32bit is_empty() const { return (used == 0); } + u32bit has_items() const { return (used != 0); } + + operator T* () { return buf; } + operator const T* () const { return buf; } + + T* begin() { return buf; } + const T* begin() const { return buf; } + + T* end() { return (buf + size()); } + const T* end() const { return (buf + size()); } + + bool operator==(const MemoryRegion& other) const + { + return (size() == other.size() && + same_mem(buf, other.buf, size())); + } + + bool operator<(const MemoryRegion&) const; + + bool operator!=(const MemoryRegion& in) const + { return (!(*this == in)); } + MemoryRegion& operator=(const MemoryRegion& in) + { if(this != &in) set(in); return (*this); } + + void copy(const T in[], u32bit n) + { copy(0, in, n); } + void copy(u32bit off, const T in[], u32bit n) + { copy_mem(buf + off, in, (n > size() - off) ? (size() - off) : n); } + + void set(const T in[], u32bit n) { create(n); copy(in, n); } + void set(const MemoryRegion& in) { set(in.begin(), in.size()); } + + void append(const T data[], u32bit n) + { grow_to(size()+n); copy(size() - n, data, n); } + void append(T x) { append(&x, 1); } + void append(const MemoryRegion& x) { append(x.begin(), x.size()); } + + void clear() { clear_mem(buf, allocated); } + void destroy() { create(0); } + + void create(u32bit); + void grow_to(u32bit); + void swap(MemoryRegion&); + + ~MemoryRegion() { deallocate(buf, allocated); } + protected: + MemoryRegion() { buf = 0; alloc = 0; used = allocated = 0; } + MemoryRegion(const MemoryRegion& other) + { + buf = 0; + used = allocated = 0; + alloc = other.alloc; + set(other.buf, other.used); + } + + void init(bool locking, u32bit length = 0) + { alloc = Allocator::get(locking); create(length); } + private: + T* allocate(u32bit n) + { + return static_cast(alloc->allocate(sizeof(T)*n)); + } + + void deallocate(T* p, u32bit n) + { alloc->deallocate(p, sizeof(T)*n); } + + T* buf; + u32bit used; + u32bit allocated; + Allocator* alloc; + }; + +/************************************************* +* Create a new buffer * +*************************************************/ +template +void MemoryRegion::create(u32bit n) + { + if(n <= allocated) { clear(); used = n; return; } + deallocate(buf, allocated); + buf = allocate(n); + allocated = used = n; + } + +/************************************************* +* Increase the size of the buffer * +*************************************************/ +template +void MemoryRegion::grow_to(u32bit n) + { + if(n > used && n <= allocated) + { + clear_mem(buf + used, n - used); + used = n; + return; + } + else if(n > allocated) + { + T* new_buf = allocate(n); + copy_mem(new_buf, buf, used); + deallocate(buf, allocated); + buf = new_buf; + allocated = used = n; + } + } + +/************************************************* +* Compare this buffer with another one * +*************************************************/ +template +bool MemoryRegion::operator<(const MemoryRegion& in) const + { + if(size() < in.size()) return true; + if(size() > in.size()) return false; + + for(u32bit j = 0; j != size(); j++) + { + if(buf[j] < in[j]) return true; + if(buf[j] > in[j]) return false; + } + + return false; + } + +/************************************************* +* Swap this buffer with another one * +*************************************************/ +template +void MemoryRegion::swap(MemoryRegion& x) + { + std::swap(buf, x.buf); + std::swap(used, x.used); + std::swap(allocated, x.allocated); + std::swap(alloc, x.alloc); + } + +/************************************************* +* Unlocked Variable Length Buffer * +*************************************************/ +template +class MemoryVector : public MemoryRegion + { + public: + MemoryVector& operator=(const MemoryRegion& in) + { if(this != &in) set(in); return (*this); } + + MemoryVector(u32bit n = 0) { MemoryRegion::init(false, n); } + MemoryVector(const T in[], u32bit n) + { MemoryRegion::init(false); set(in, n); } + MemoryVector(const MemoryRegion& in) + { MemoryRegion::init(false); set(in); } + MemoryVector(const MemoryRegion& in1, const MemoryRegion& in2) + { MemoryRegion::init(false); set(in1); append(in2); } + }; + +/************************************************* +* Locked Variable Length Buffer * +*************************************************/ +template +class SecureVector : public MemoryRegion + { + public: + SecureVector& operator=(const MemoryRegion& in) + { if(this != &in) set(in); return (*this); } + + SecureVector(u32bit n = 0) { MemoryRegion::init(true, n); } + SecureVector(const T in[], u32bit n) + { MemoryRegion::init(true); set(in, n); } + SecureVector(const MemoryRegion& in) + { MemoryRegion::init(true); set(in); } + SecureVector(const MemoryRegion& in1, const MemoryRegion& in2) + { MemoryRegion::init(true); set(in1); append(in2); } + }; + +/************************************************* +* Locked Fixed Length Buffer * +*************************************************/ +template +class SecureBuffer : public MemoryRegion + { + public: + SecureBuffer& operator=(const SecureBuffer& in) + { if(this != &in) set(in); return (*this); } + + SecureBuffer() { MemoryRegion::init(true, L); } + SecureBuffer(const T in[], u32bit n) + { MemoryRegion::init(true, L); copy(in, n); } + private: + SecureBuffer& operator=(const MemoryRegion& in) + { if(this != &in) set(in); return (*this); } + }; + +} + +#endif -- cgit v1.2.3