aboutsummaryrefslogtreecommitdiffstats
path: root/src/utils
diff options
context:
space:
mode:
authorlloyd <[email protected]>2008-11-08 20:06:27 +0000
committerlloyd <[email protected]>2008-11-08 20:06:27 +0000
commit73ba6c48e349955f05e81d674172c9c737540280 (patch)
treebb5636fc4e444b73d72c8a62b7fffd4310541347 /src/utils
parent39f29e53a346eed9671a108b6aa59eb78b1dc084 (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.h124
-rw-r--r--src/utils/data_src.cpp205
-rw-r--r--src/utils/data_src.h148
-rw-r--r--src/utils/exceptn.cpp60
-rw-r--r--src/utils/exceptn.h195
-rw-r--r--src/utils/info.txt8
-rw-r--r--src/utils/secmem.h435
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 = &in;
+ 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