diff options
author | lloyd <[email protected]> | 2008-11-08 20:06:27 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2008-11-08 20:06:27 +0000 |
commit | 73ba6c48e349955f05e81d674172c9c737540280 (patch) | |
tree | bb5636fc4e444b73d72c8a62b7fffd4310541347 /src/utils | |
parent | 39f29e53a346eed9671a108b6aa59eb78b1dc084 (diff) |
Move most of what was left in core to utils (since that is what they are,
basically). buf_comp and data_src might need their own directory, but it
doesn't really feel like it.
Diffstat (limited to 'src/utils')
-rw-r--r-- | src/utils/buf_comp.h | 124 | ||||
-rw-r--r-- | src/utils/data_src.cpp | 205 | ||||
-rw-r--r-- | src/utils/data_src.h | 148 | ||||
-rw-r--r-- | src/utils/exceptn.cpp | 60 | ||||
-rw-r--r-- | src/utils/exceptn.h | 195 | ||||
-rw-r--r-- | src/utils/info.txt | 8 | ||||
-rw-r--r-- | src/utils/secmem.h | 435 |
7 files changed, 1174 insertions, 1 deletions
diff --git a/src/utils/buf_comp.h b/src/utils/buf_comp.h new file mode 100644 index 000000000..c05324b8f --- /dev/null +++ b/src/utils/buf_comp.h @@ -0,0 +1,124 @@ +/** +* BufferedComputation +* (C) 1999-2007 Jack Lloyd +*/ + +#ifndef BOTAN_BUFFERED_COMPUTATION_H__ +#define BOTAN_BUFFERED_COMPUTATION_H__ + +#include <botan/secmem.h> + +namespace Botan { + +/** +* This class represents any kind of computation which +* uses an internal state, +* such as hash functions. +*/ +class BOTAN_DLL BufferedComputation + { + public: + + /** + * The length of the output of this function in bytes. + */ + const u32bit OUTPUT_LENGTH; + + /** + * Add new input to process. + * @param in the input to process as a byte array + * @param the length of the byte array + */ + void update(const byte in[], u32bit length) { add_data(in, length); } + + /** + * Add new input to process. + * @param in the input to process as a MemoryRegion + */ + void update(const MemoryRegion<byte>& in) { add_data(in, in.size()); } + + /** + * Add new input to process. + * @param str the input to process as a std::string. Will be interpreted + * as a byte array based on + * the strings encoding. + */ + void update(const std::string& str) + { + add_data(reinterpret_cast<const byte*>(str.data()), str.size()); + } + + /** + * Process a single byte. + * @param in the byte to process + */ + void update(byte in) { add_data(&in, 1); } + + /** + * Complete the computation and retrieve the + * final result. + * @param out The byte array to be filled with the result. + * Must be of length OUTPUT_LENGTH. + */ + void final(byte out[]) { final_result(out); } + + /** + * Complete the computation and retrieve the + * final result. + * @return a SecureVector holding the result + */ + SecureVector<byte> final() + { + SecureVector<byte> output(OUTPUT_LENGTH); + final_result(output); + return output; + } + + /** + * Update and finalize computation. Does the same as calling update() + * and final() consecutively. + * @param in the input to process as a byte array + * @param length the length of the byte array + * @result the result of the call to final() + */ + SecureVector<byte> process(const byte in[], u32bit length) + { + add_data(in, length); + return final(); + } + + /** + * Update and finalize computation. Does the same as calling update() + * and final() consecutively. + * @param in the input to process + * @result the result of the call to final() + */ + SecureVector<byte> process(const MemoryRegion<byte>& in) + { + add_data(in, in.size()); + return final(); + } + + /** + * Update and finalize computation. Does the same as calling update() + * and final() consecutively. + * @param in the input to process as a string + * @result the result of the call to final() + */ + SecureVector<byte> process(const std::string& in) + { + update(in); + return final(); + } + + BufferedComputation(u32bit out_len) : OUTPUT_LENGTH(out_len) {} + virtual ~BufferedComputation() {} + private: + BufferedComputation& operator=(const BufferedComputation&); + virtual void add_data(const byte[], u32bit) = 0; + virtual void final_result(byte[]) = 0; + }; + +} + +#endif diff --git a/src/utils/data_src.cpp b/src/utils/data_src.cpp new file mode 100644 index 000000000..de5544885 --- /dev/null +++ b/src/utils/data_src.cpp @@ -0,0 +1,205 @@ +/************************************************* +* DataSource Source File * +* (C) 1999-2007 Jack Lloyd * +* 2005 Matthew Gregan * +*************************************************/ + +#include <botan/data_src.h> +#include <botan/exceptn.h> + +#include <fstream> +#include <algorithm> + +namespace Botan { + +/************************************************* +* Read a single byte from the DataSource * +*************************************************/ +u32bit DataSource::read_byte(byte& out) + { + return read(&out, 1); + } + +/************************************************* +* Peek a single byte from the DataSource * +*************************************************/ +u32bit DataSource::peek_byte(byte& out) const + { + return peek(&out, 1, 0); + } + +/************************************************* +* Discard the next N bytes of the data * +*************************************************/ +u32bit DataSource::discard_next(u32bit n) + { + u32bit discarded = 0; + byte dummy; + for(u32bit j = 0; j != n; ++j) + discarded = read_byte(dummy); + return discarded; + } + +/************************************************* +* Read from a memory buffer * +*************************************************/ +u32bit DataSource_Memory::read(byte out[], u32bit length) + { + u32bit got = std::min(source.size() - offset, length); + copy_mem(out, source + offset, got); + offset += got; + return got; + } + +/************************************************* +* Peek into a memory buffer * +*************************************************/ +u32bit DataSource_Memory::peek(byte out[], u32bit length, + u32bit peek_offset) const + { + const u32bit bytes_left = source.size() - offset; + if(peek_offset >= bytes_left) return 0; + + u32bit got = std::min(bytes_left - peek_offset, length); + copy_mem(out, source + offset + peek_offset, got); + return got; + } + +/************************************************* +* Check if the memory buffer is empty * +*************************************************/ +bool DataSource_Memory::end_of_data() const + { + return (offset == source.size()); + } + +/************************************************* +* DataSource_Memory Constructor * +*************************************************/ +DataSource_Memory::DataSource_Memory(const byte in[], u32bit length) + { + source.set(in, length); + offset = 0; + } + +/************************************************* +* DataSource_Memory Constructor * +*************************************************/ +DataSource_Memory::DataSource_Memory(const MemoryRegion<byte>& in) + { + source = in; + offset = 0; + } + +/************************************************* +* DataSource_Memory Constructor * +*************************************************/ +DataSource_Memory::DataSource_Memory(const std::string& in) + { + source.set(reinterpret_cast<const byte*>(in.data()), in.length()); + offset = 0; + } + +/************************************************* +* Read from a stream * +*************************************************/ +u32bit DataSource_Stream::read(byte out[], u32bit length) + { + source->read(reinterpret_cast<char*>(out), length); + if(source->bad()) + throw Stream_IO_Error("DataSource_Stream::read: Source failure"); + + u32bit got = source->gcount(); + total_read += got; + return got; + } + +/************************************************* +* Peek into a stream * +*************************************************/ +u32bit DataSource_Stream::peek(byte out[], u32bit length, u32bit offset) const + { + if(end_of_data()) + throw Invalid_State("DataSource_Stream: Cannot peek when out of data"); + + u32bit got = 0; + + if(offset) + { + SecureVector<byte> buf(offset); + source->read(reinterpret_cast<char*>(buf.begin()), buf.size()); + if(source->bad()) + throw Stream_IO_Error("DataSource_Stream::peek: Source failure"); + got = source->gcount(); + } + + if(got == offset) + { + source->read(reinterpret_cast<char*>(out), length); + if(source->bad()) + throw Stream_IO_Error("DataSource_Stream::peek: Source failure"); + got = source->gcount(); + } + + if(source->eof()) + source->clear(); + source->seekg(total_read, std::ios::beg); + + return got; + } + +/************************************************* +* Check if the stream is empty or in error * +*************************************************/ +bool DataSource_Stream::end_of_data() const + { + return (!source->good()); + } + +/************************************************* +* Return a human-readable ID for this stream * +*************************************************/ +std::string DataSource_Stream::id() const + { + return identifier; + } + +/************************************************* +* DataSource_Stream Constructor * +*************************************************/ +DataSource_Stream::DataSource_Stream(const std::string& path, + bool use_binary) : + identifier(path), owner(true) + { + if(use_binary) + source = new std::ifstream(path.c_str(), std::ios::binary); + else + source = new std::ifstream(path.c_str()); + + if(!source->good()) + throw Stream_IO_Error("DataSource: Failure opening file " + path); + + total_read = 0; + } + +/************************************************* +* DataSource_Stream Constructor * +*************************************************/ +DataSource_Stream::DataSource_Stream(std::istream& in, + const std::string& name) : + identifier(name), owner(false) + { + source = ∈ + total_read = 0; + } + +/************************************************* +* DataSource_Stream Destructor * +*************************************************/ +DataSource_Stream::~DataSource_Stream() + { + if(owner) + delete source; + } + +} diff --git a/src/utils/data_src.h b/src/utils/data_src.h new file mode 100644 index 000000000..25bdce00f --- /dev/null +++ b/src/utils/data_src.h @@ -0,0 +1,148 @@ +/************************************************* +* DataSource Header File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#ifndef BOTAN_DATA_SRC_H__ +#define BOTAN_DATA_SRC_H__ + +#include <botan/secmem.h> +#include <string> +#include <iosfwd> + +namespace Botan { + +/** +* This class represents an abstract data source object. +*/ +class BOTAN_DLL DataSource + { + public: + /** + * Read from the source. Moves the internal offset so that + * every call to read will return a new portion of the source. + * @param out the byte array to write the result to + * @param length the length of the byte array out + * @return the length in bytes that was actually read and put + * into out + */ + virtual u32bit read(byte out[], u32bit length) = 0; + + /** + * Read from the source but do not modify the internal offset. Consecutive + * calls to peek() will return portions of the source starting at the same + * position. + * @param out the byte array to write the output to + * @param length the length of the byte array out + * @return the length in bytes that was actually read and put + * into out + */ + virtual u32bit peek(byte out[], u32bit length, + u32bit peek_offset) const = 0; + + /** + * Test whether the source still has data that can be read. + * @return true if there is still data to read, false otherwise + */ + virtual bool end_of_data() const = 0; + /** + * return the id of this data source + * @return the std::string representing the id of this data source + */ + virtual std::string id() const { return ""; } + + /** + * Read one byte. + * @param the byte to read to + * @return the length in bytes that was actually read and put + * into out + */ + u32bit read_byte(byte& out); + + /** + * Peek at one byte. + * @param the byte to read to + * @return the length in bytes that was actually read and put + * into out + */ + u32bit peek_byte(byte& out) const; + + /** + * Discard the next N bytes of the data + * @param N the number of bytes to discard + * @return the number of bytes actually discarded + */ + u32bit discard_next(u32bit N); + + DataSource() {} + virtual ~DataSource() {} + private: + DataSource& operator=(const DataSource&) { return (*this); } + DataSource(const DataSource&); + }; + +/** +* This class represents a Memory-Based DataSource +*/ +class BOTAN_DLL DataSource_Memory : public DataSource + { + public: + u32bit read(byte[], u32bit); + u32bit peek(byte[], u32bit, u32bit) const; + bool end_of_data() const; + + /** + * Construct a memory source that reads from a string + * @param in the string to read from + */ + DataSource_Memory(const std::string& in); + + /** + * Construct a memory source that reads from a byte array + * @param in the byte array to read from + * @param length the length of the byte array + */ + DataSource_Memory(const byte in[], u32bit length); + + /** + * Construct a memory source that reads from a MemoryRegion + * @param in the MemoryRegion to read from + */ + DataSource_Memory(const MemoryRegion<byte>& in); + private: + SecureVector<byte> source; + u32bit offset; + }; + +/** +* This class represents a Stream-Based DataSource. +*/ +class BOTAN_DLL DataSource_Stream : public DataSource + { + public: + u32bit read(byte[], u32bit); + u32bit peek(byte[], u32bit, u32bit) const; + bool end_of_data() const; + std::string id() const; + + DataSource_Stream(std::istream&, const std::string& id = ""); + + /** + * Construct a Stream-Based DataSource from file + * @param file the name of the file + * @param use_binary whether to treat the file as binary or not + */ + DataSource_Stream(const std::string& file, bool use_binary = false); + + ~DataSource_Stream(); + private: + const std::string identifier; + const bool owner; + + std::istream* source; + u32bit total_read; + }; + +} + +#endif diff --git a/src/utils/exceptn.cpp b/src/utils/exceptn.cpp new file mode 100644 index 000000000..29357afa5 --- /dev/null +++ b/src/utils/exceptn.cpp @@ -0,0 +1,60 @@ +/************************************************* +* Exceptions Source File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#include <botan/exceptn.h> +#include <botan/parsing.h> + +namespace Botan { + +/************************************************* +* Constructor for Invalid_Key_Length * +*************************************************/ +Invalid_Key_Length::Invalid_Key_Length(const std::string& name, u32bit length) + { + set_msg(name + " cannot accept a key of length " + to_string(length)); + } + +/************************************************* +* Constructor for Invalid_Block_Size * +*************************************************/ +Invalid_Block_Size::Invalid_Block_Size(const std::string& mode, + const std::string& pad) + { + set_msg("Padding method " + pad + " cannot be used with " + mode); + } + +/************************************************* +* Constructor for Invalid_IV_Length * +*************************************************/ +Invalid_IV_Length::Invalid_IV_Length(const std::string& mode, u32bit bad_len) + { + set_msg("IV length " + to_string(bad_len) + " is invalid for " + mode); + } + +/************************************************* +* Constructor for Algorithm_Not_Found * +*************************************************/ +Algorithm_Not_Found::Algorithm_Not_Found(const std::string& name) + { + set_msg("Could not find any algorithm named \"" + name + "\""); + } + +/************************************************* +* Constructor for Invalid_Algorithm_Name * +*************************************************/ +Invalid_Algorithm_Name::Invalid_Algorithm_Name(const std::string& name) + { + set_msg("Invalid algorithm name: " + name); + } + +/************************************************* +* Constructor for Config_Error * +*************************************************/ +Config_Error::Config_Error(const std::string& err, u32bit line) + { + set_msg("Config error at line " + to_string(line) + ": " + err); + } + +} diff --git a/src/utils/exceptn.h b/src/utils/exceptn.h new file mode 100644 index 000000000..3bfec2fd2 --- /dev/null +++ b/src/utils/exceptn.h @@ -0,0 +1,195 @@ +/************************************************* +* Exceptions Header File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#ifndef BOTAN_EXCEPTION_H__ +#define BOTAN_EXCEPTION_H__ + +#include <botan/types.h> +#include <exception> +#include <string> + +namespace Botan { + +/************************************************* +* Exception Base Class * +*************************************************/ +class BOTAN_DLL Exception : public std::exception + { + public: + const char* what() const throw() { return msg.c_str(); } + Exception(const std::string& m = "Unknown error") { set_msg(m); } + virtual ~Exception() throw() {} + protected: + void set_msg(const std::string& m) { msg = "Botan: " + m; } + private: + std::string msg; + }; + +/************************************************* +* Invalid_Argument Exception * +*************************************************/ +struct BOTAN_DLL Invalid_Argument : public Exception + { + Invalid_Argument(const std::string& err = "") : Exception(err) {} + }; + +/************************************************* +* Invalid_Key_Length Exception * +*************************************************/ +struct BOTAN_DLL Invalid_Key_Length : public Invalid_Argument + { + Invalid_Key_Length(const std::string&, u32bit); + }; + +/************************************************* +* Invalid_Block_Size Exception * +*************************************************/ +struct BOTAN_DLL Invalid_Block_Size : public Invalid_Argument + { + Invalid_Block_Size(const std::string&, const std::string&); + }; + +/************************************************* +* Invalid_IV_Length Exception * +*************************************************/ +struct BOTAN_DLL Invalid_IV_Length : public Invalid_Argument + { + Invalid_IV_Length(const std::string&, u32bit); + }; + +/************************************************* +* Invalid_State Exception * +*************************************************/ +struct BOTAN_DLL Invalid_State : public Exception + { + Invalid_State(const std::string& err) : Exception(err) {} + }; + +/************************************************* +* PRNG_Unseeded Exception * +*************************************************/ +struct BOTAN_DLL PRNG_Unseeded : public Invalid_State + { + PRNG_Unseeded(const std::string& algo) : + Invalid_State("PRNG not seeded: " + algo) {} + }; + +/************************************************* +* Policy_Violation Exception * +*************************************************/ +struct BOTAN_DLL Policy_Violation : public Invalid_State + { + Policy_Violation(const std::string& err) : + Invalid_State("Policy violation: " + err) {} + }; + +/************************************************* +* Lookup_Error Exception * +*************************************************/ +struct BOTAN_DLL Lookup_Error : public Exception + { + Lookup_Error(const std::string& err) : Exception(err) {} + }; + +/************************************************* +* Algorithm_Not_Found Exception * +*************************************************/ +struct BOTAN_DLL Algorithm_Not_Found : public Exception + { + Algorithm_Not_Found(const std::string&); + }; + +/************************************************* +* Format_Error Exception * +*************************************************/ +struct BOTAN_DLL Format_Error : public Exception + { + Format_Error(const std::string& err = "") : Exception(err) {} + }; + +/************************************************* +* Invalid_Algorithm_Name Exception * +*************************************************/ +struct BOTAN_DLL Invalid_Algorithm_Name : public Format_Error + { + Invalid_Algorithm_Name(const std::string&); + }; + +/************************************************* +* Encoding_Error Exception * +*************************************************/ +struct BOTAN_DLL Encoding_Error : public Format_Error + { + Encoding_Error(const std::string& name) : + Format_Error("Encoding error: " + name) {} + }; + +/************************************************* +* Decoding_Error Exception * +*************************************************/ +struct BOTAN_DLL Decoding_Error : public Format_Error + { + Decoding_Error(const std::string& name) : + Format_Error("Decoding error: " + name) {} + }; + +/************************************************* +* Invalid_OID Exception * +*************************************************/ +struct BOTAN_DLL Invalid_OID : public Decoding_Error + { + Invalid_OID(const std::string& oid) : + Decoding_Error("Invalid ASN.1 OID: " + oid) {} + }; + +/************************************************* +* Stream_IO_Error Exception * +*************************************************/ +struct BOTAN_DLL Stream_IO_Error : public Exception + { + Stream_IO_Error(const std::string& err) : + Exception("I/O error: " + err) {} + }; + +/************************************************* +* Configuration Error Exception * +*************************************************/ +struct BOTAN_DLL Config_Error : public Format_Error + { + Config_Error(const std::string& err) : + Format_Error("Config error: " + err) {} + Config_Error(const std::string&, u32bit); + }; + +/************************************************* +* Integrity Failure Exception * +*************************************************/ +struct BOTAN_DLL Integrity_Failure : public Exception + { + Integrity_Failure(const std::string& err) : + Exception("Integrity failure: " + err) {} + }; + +/************************************************* +* Internal_Error Exception * +*************************************************/ +struct BOTAN_DLL Internal_Error : public Exception + { + Internal_Error(const std::string& err) : + Exception("Internal error: " + err) {} + }; + +/************************************************* +* Self Test Failure Exception * +*************************************************/ +struct BOTAN_DLL Self_Test_Failure : public Internal_Error + { + Self_Test_Failure(const std::string& err) : + Internal_Error("Self test failed: " + err) {} + }; + +} + +#endif diff --git a/src/utils/info.txt b/src/utils/info.txt index 127ea5e2f..4999a08e7 100644 --- a/src/utils/info.txt +++ b/src/utils/info.txt @@ -15,12 +15,17 @@ filters <add> bit_ops.h bswap.h +buf_comp.h charset.cpp charset.h +data_src.cpp +data_src.h datastor.cpp datastor.h -entropy.h entropy.cpp +entropy.h +exceptn.cpp +exceptn.h loadstor.h mem_ops.h mlock.cpp @@ -28,6 +33,7 @@ mutex.h parsing.cpp parsing.h rotate.h +secmem.h stl_util.h types.h ui.cpp diff --git a/src/utils/secmem.h b/src/utils/secmem.h new file mode 100644 index 000000000..8e353a68b --- /dev/null +++ b/src/utils/secmem.h @@ -0,0 +1,435 @@ +/************************************************* +* Secure Memory Buffers Header File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#ifndef BOTAN_SECURE_MEMORY_BUFFERS_H__ +#define BOTAN_SECURE_MEMORY_BUFFERS_H__ + +#include <botan/allocate.h> +#include <botan/mem_ops.h> + +namespace Botan { + +/** +* This class represents variable length memory buffers. +*/ +template<typename T> +class MemoryRegion + { + public: + /** + * Find out the size of the buffer, i.e. how many objects of type T it + * contains. + * @return the size of the buffer + */ + u32bit size() const { return used; } + + /** + * Find out whether this buffer is empty. + * @return true if the buffer is empty, false otherwise + */ + bool is_empty() const { return (used == 0); } + + /** + * Find out whether this buffer is non-empty + * @return true if the buffer is non-empty, false otherwise + */ + bool has_items() const { return (used != 0); } + + /** + * Get a pointer to the first element in the buffer. + * @return a pointer to the first element in the buffer + */ + operator T* () { return buf; } + + /** + * Get a constant pointer to the first element in the buffer. + * @return a constant pointer to the first element in the buffer + */ + operator const T* () const { return buf; } + + /** + * Get a pointer to the first element in the buffer. + * @return a pointer to the first element in the buffer + */ + T* begin() { return buf; } + + /** + * Get a constant pointer to the first element in the buffer. + * @return a constant pointer to the first element in the buffer + */ + const T* begin() const { return buf; } + + /** + * Get a pointer to the last element in the buffer. + * @return a pointer to the last element in the buffer + */ + T* end() { return (buf + size()); } + + /** + * Get a constant pointer to the last element in the buffer. + * @return a constant pointer to the last element in the buffer + */ + const T* end() const { return (buf + size()); } + + /** + * Check two buffers for equality. + * @return true iff the content of both buffers is byte-wise equal + */ + bool operator==(const MemoryRegion<T>& other) const + { + return (size() == other.size() && + same_mem(buf, other.buf, size())); + } + + /** + * Compare two buffers lexicographically. + * @return true if this buffer is lexicographically smaller than other. + */ + bool operator<(const MemoryRegion<T>& other) const; + + /** + * Check two buffers for inequality. + * @return false if the content of both buffers is byte-wise equal, true + * otherwise. + */ + bool operator!=(const MemoryRegion<T>& in) const + { return (!(*this == in)); } + + /** + * Copy the contents of another buffer into this buffer. + * The former contents of *this are discarded. + * @param in the buffer to copy the contents from. + * @return a reference to *this + */ + MemoryRegion<T>& operator=(const MemoryRegion<T>& in) + { if(this != &in) set(in); return (*this); } + + /** + * The use of this function is discouraged because of the risk of memory + * errors. Use MemoryRegion<T>::set() + * instead. + * Copy the contents of an array of objects of type T into this buffer. + * The former contents of *this are discarded. + * The length of *this must be at least n, otherwise memory errors occur. + * @param in the array to copy the contents from + * @param n the length of in + */ + void copy(const T in[], u32bit n) + { copy(0, in, n); } + + /** + * The use of this function is discouraged because of the risk of memory + * errors. Use MemoryRegion<T>::set() + * instead. + * Copy the contents of an array of objects of type T into this buffer. + * The former contents of *this are discarded. + * The length of *this must be at least n, otherwise memory errors occur. + * @param off the offset position inside this buffer to start inserting + * the copied bytes + * @param in the array to copy the contents from + * @param n the length of in + */ + void copy(u32bit off, const T in[], u32bit n) + { copy_mem(buf + off, in, (n > size() - off) ? (size() - off) : n); } + + /** + * Set the contents of this according to the argument. The size of + * *this is increased if necessary. + * @param in the array of objects of type T to copy the contents from + * @param n the size of array in + */ + void set(const T in[], u32bit n) { create(n); copy(in, n); } + + /** + * Set the contents of this according to the argument. The size of + * *this is increased if necessary. + * @param in the buffer to copy the contents from + */ + void set(const MemoryRegion<T>& in) { set(in.begin(), in.size()); } + + /** + * Append data to the end of this buffer. + * @param data the array containing the data to append + * @param n the size of the array data + */ + void append(const T data[], u32bit n) + { grow_to(size()+n); copy(size() - n, data, n); } + + /** + * Append a single element. + * @param x the element to append + */ + void append(T x) { append(&x, 1); } + + /** + * Append data to the end of this buffer. + * @param data the buffer containing the data to append + */ + void append(const MemoryRegion<T>& x) { append(x.begin(), x.size()); } + + /** + * Zeroise the bytes of this buffer. The length remains unchanged. + */ + void clear() { clear_mem(buf, allocated); } + + /** + * Reset this buffer to an empty buffer with size zero. + */ + void destroy() { create(0); } + + /** + * Reset this buffer to a buffer of specified length. The content will be + * initialized to zero bytes. + * @param n the new length of the buffer + */ + void create(u32bit n); + + /** + * Preallocate memory, so that this buffer can grow up to size n without + * having to perform any actual memory allocations. (This is + * the same principle as for std::vector::reserve().) + */ + void grow_to(u32bit N); + + /** + * Swap this buffer with another object. + */ + void swap(MemoryRegion<T>& other); + + ~MemoryRegion() { deallocate(buf, allocated); } + protected: + MemoryRegion() { buf = 0; alloc = 0; used = allocated = 0; } + MemoryRegion(const MemoryRegion<T>& 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<T*>(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<typename T> +void MemoryRegion<T>::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<typename T> +void MemoryRegion<T>::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<typename T> +bool MemoryRegion<T>::operator<(const MemoryRegion<T>& 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<typename T> +void MemoryRegion<T>::swap(MemoryRegion<T>& x) + { + std::swap(buf, x.buf); + std::swap(used, x.used); + std::swap(allocated, x.allocated); + std::swap(alloc, x.alloc); + } + +/** +* This class represents variable length buffers that do not +* make use of memory locking. +*/ +template<typename T> +class MemoryVector : public MemoryRegion<T> + { + public: + /** + * Copy the contents of another buffer into this buffer. + * @param in the buffer to copy the contents from + * @return a reference to *this + */ + MemoryVector<T>& operator=(const MemoryRegion<T>& in) + { if(this != &in) set(in); return (*this); } + + /** + * Create a buffer of the specified length. + * @param n the length of the buffer to create. + * + */ + MemoryVector(u32bit n = 0) { MemoryRegion<T>::init(false, n); } + + /** + * Create a buffer with the specified contents. + * @param in the array containing the data to be initially copied + * into the newly created buffer + * @param n the size of the arry in + */ + MemoryVector(const T in[], u32bit n) + { MemoryRegion<T>::init(false); set(in, n); } + + /** + * Copy constructor. + */ + MemoryVector(const MemoryRegion<T>& in) + { MemoryRegion<T>::init(false); set(in); } + + /** + * Create a buffer whose content is the concatenation of two other + * buffers. + * @param in1 the first part of the new contents + * @param in2 the contents to be appended to in1 + */ + MemoryVector(const MemoryRegion<T>& in1, const MemoryRegion<T>& in2) + { MemoryRegion<T>::init(false); set(in1); append(in2); } + }; + +/** +* This class represents variable length buffers using the operating +* systems capability to lock memory, i.e. keeping it from being +* swapped out to disk. In this way, a security hole allowing attackers +* to find swapped out secret keys is closed. Please refer to +* Botan::InitializerOptions::secure_memory() for restrictions and +* further details. +*/ +template<typename T> +class SecureVector : public MemoryRegion<T> + { + public: + /** + * Copy the contents of another buffer into this buffer. + * @param in the buffer to copy the contents from + * @return a reference to *this + */ + SecureVector<T>& operator=(const MemoryRegion<T>& in) + { if(this != &in) set(in); return (*this); } + + /** + * Create a buffer of the specified length. + * @param n the length of the buffer to create. + * + */ + SecureVector(u32bit n = 0) { MemoryRegion<T>::init(true, n); } + + /** + * Create a buffer with the specified contents. + * @param in the array containing the data to be initially copied + * into the newly created buffer + * @param n the size of the array in + */ + SecureVector(const T in[], u32bit n) + { MemoryRegion<T>::init(true); set(in, n); } + + /** + * Create a buffer with contents specified contents. + * @param in the buffer holding the contents that will be + * copied into the newly created buffer. + */ + SecureVector(const MemoryRegion<T>& in) + { MemoryRegion<T>::init(true); set(in); } + + /** + * Create a buffer whose content is the concatenation of two other + * buffers. + * @param in1 the first part of the new contents + * @param in2 the contents to be appended to in1 + */ + SecureVector(const MemoryRegion<T>& in1, const MemoryRegion<T>& in2) + { MemoryRegion<T>::init(true); set(in1); append(in2); } + }; + +/** +* This class represents fixed length buffers using the operating +* systems capability to lock memory, i.e. keeping it from being +* swapped out to disk. In this way, a security hole allowing attackers +* to find swapped out secret keys is closed. Please refer to +* Botan::InitializerOptions::secure_memory() for restrictions and +* further details. +*/ +template<typename T, u32bit L> +class SecureBuffer : public MemoryRegion<T> + { + public: + /** + * Copy the contents of another buffer into this buffer. + * @param in the buffer to copy the contents from + * @return a reference to *this + */ + SecureBuffer<T,L>& operator=(const SecureBuffer<T,L>& in) + { if(this != &in) set(in); return (*this); } + + /** + * Create a buffer of the length L. + */ + SecureBuffer() { MemoryRegion<T>::init(true, L); } + + /** + * Create a buffer of size L with the specified contents. + * @param in the array containing the data to be initially copied + * into the newly created buffer + * @param n the size of the array in + */ + SecureBuffer(const T in[], u32bit n) + { MemoryRegion<T>::init(true, L); copy(in, n); } + private: + SecureBuffer<T, L>& operator=(const MemoryRegion<T>& in) + { if(this != &in) set(in); return (*this); } + }; + +} + +#endif |