summaryrefslogtreecommitdiffstats
path: root/botan/src/filters
diff options
context:
space:
mode:
Diffstat (limited to 'botan/src/filters')
-rw-r--r--botan/src/filters/algo_filt.cpp124
-rw-r--r--botan/src/filters/basefilt.cpp74
-rw-r--r--botan/src/filters/basefilt.h99
-rw-r--r--botan/src/filters/buf_filt.cpp71
-rw-r--r--botan/src/filters/buf_filt.h39
-rw-r--r--botan/src/filters/data_snk.cpp62
-rw-r--r--botan/src/filters/data_snk.h65
-rw-r--r--botan/src/filters/data_src.cpp207
-rw-r--r--botan/src/filters/data_src.h150
-rw-r--r--botan/src/filters/fd_unix/fd_unix.cpp53
-rw-r--r--botan/src/filters/fd_unix/fd_unix.h23
-rw-r--r--botan/src/filters/fd_unix/info.txt28
-rw-r--r--botan/src/filters/filter.cpp127
-rw-r--r--botan/src/filters/filter.h113
-rw-r--r--botan/src/filters/filters.h189
-rw-r--r--botan/src/filters/info.txt41
-rw-r--r--botan/src/filters/out_buf.cpp119
-rw-r--r--botan/src/filters/out_buf.h43
-rw-r--r--botan/src/filters/pbe.h56
-rw-r--r--botan/src/filters/pipe.cpp306
-rw-r--r--botan/src/filters/pipe.h275
-rw-r--r--botan/src/filters/pipe_io.cpp45
-rw-r--r--botan/src/filters/pipe_rw.cpp167
-rw-r--r--botan/src/filters/secqueue.cpp205
-rw-r--r--botan/src/filters/secqueue.h43
25 files changed, 2724 insertions, 0 deletions
diff --git a/botan/src/filters/algo_filt.cpp b/botan/src/filters/algo_filt.cpp
new file mode 100644
index 0000000..23f7a20
--- /dev/null
+++ b/botan/src/filters/algo_filt.cpp
@@ -0,0 +1,124 @@
+/*
+* Filters
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/filters.h>
+#include <botan/libstate.h>
+#include <algorithm>
+
+namespace Botan {
+
+/*
+* StreamCipher_Filter Constructor
+*/
+StreamCipher_Filter::StreamCipher_Filter(const std::string& sc_name) :
+ buffer(DEFAULT_BUFFERSIZE)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+ base_ptr = cipher = af.make_stream_cipher(sc_name);
+ }
+
+/*
+* StreamCipher_Filter Constructor
+*/
+StreamCipher_Filter::StreamCipher_Filter(StreamCipher* stream_cipher) :
+ buffer(DEFAULT_BUFFERSIZE)
+ {
+ base_ptr = cipher = stream_cipher;
+ }
+
+/*
+* StreamCipher_Filter Constructor
+*/
+StreamCipher_Filter::StreamCipher_Filter(const std::string& sc_name,
+ const SymmetricKey& key) :
+ buffer(DEFAULT_BUFFERSIZE)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+ base_ptr = cipher = af.make_stream_cipher(sc_name);
+ cipher->set_key(key);
+ }
+
+/*
+* Set the IV of a stream cipher
+*/
+void StreamCipher_Filter::set_iv(const InitializationVector& iv)
+ {
+ cipher->resync(iv.begin(), iv.length());
+ }
+
+/*
+* Write data into a StreamCipher_Filter
+*/
+void StreamCipher_Filter::write(const byte input[], u32bit length)
+ {
+ while(length)
+ {
+ u32bit copied = std::min(length, buffer.size());
+ cipher->encrypt(input, buffer, copied);
+ send(buffer, copied);
+ input += copied;
+ length -= copied;
+ }
+ }
+
+/*
+* Hash_Filter Constructor
+*/
+Hash_Filter::Hash_Filter(const std::string& algo_spec,
+ u32bit len) :
+ OUTPUT_LENGTH(len)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+ hash = af.make_hash_function(algo_spec);
+ }
+
+/*
+* Complete a calculation by a Hash_Filter
+*/
+void Hash_Filter::end_msg()
+ {
+ SecureVector<byte> output = hash->final();
+ if(OUTPUT_LENGTH)
+ send(output, std::min(OUTPUT_LENGTH, output.size()));
+ else
+ send(output);
+ }
+
+/*
+* MAC_Filter Constructor
+*/
+MAC_Filter::MAC_Filter(const std::string& mac_name, u32bit len) :
+ OUTPUT_LENGTH(len)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+ base_ptr = mac = af.make_mac(mac_name);
+ }
+
+/*
+* MAC_Filter Constructor
+*/
+MAC_Filter::MAC_Filter(const std::string& mac_name, const SymmetricKey& key,
+ u32bit len) : OUTPUT_LENGTH(len)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+ base_ptr = mac = af.make_mac(mac_name);
+ mac->set_key(key);
+ }
+
+/*
+* Complete a calculation by a MAC_Filter
+*/
+void MAC_Filter::end_msg()
+ {
+ SecureVector<byte> output = mac->final();
+ if(OUTPUT_LENGTH)
+ send(output, std::min(OUTPUT_LENGTH, output.size()));
+ else
+ send(output);
+ }
+
+}
diff --git a/botan/src/filters/basefilt.cpp b/botan/src/filters/basefilt.cpp
new file mode 100644
index 0000000..02dbd8a
--- /dev/null
+++ b/botan/src/filters/basefilt.cpp
@@ -0,0 +1,74 @@
+/*
+* Basic Filters
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/basefilt.h>
+
+namespace Botan {
+
+/*
+* Chain Constructor
+*/
+Chain::Chain(Filter* f1, Filter* f2, Filter* f3, Filter* f4)
+ {
+ if(f1) { attach(f1); incr_owns(); }
+ if(f2) { attach(f2); incr_owns(); }
+ if(f3) { attach(f3); incr_owns(); }
+ if(f4) { attach(f4); incr_owns(); }
+ }
+
+/*
+* Chain Constructor
+*/
+Chain::Chain(Filter* filters[], u32bit count)
+ {
+ for(u32bit j = 0; j != count; ++j)
+ if(filters[j])
+ {
+ attach(filters[j]);
+ incr_owns();
+ }
+ }
+
+/*
+* Fork Constructor
+*/
+Fork::Fork(Filter* f1, Filter* f2, Filter* f3, Filter* f4)
+ {
+ Filter* filters[4] = { f1, f2, f3, f4 };
+ set_next(filters, 4);
+ }
+
+/*
+* Fork Constructor
+*/
+Fork::Fork(Filter* filters[], u32bit count)
+ {
+ set_next(filters, count);
+ }
+
+/*
+* Set the algorithm key
+*/
+void Keyed_Filter::set_key(const SymmetricKey& key)
+ {
+ if(base_ptr)
+ base_ptr->set_key(key);
+ else
+ throw Invalid_State("Keyed_Filter::set_key: No base algorithm set");
+ }
+
+/*
+* Check if a keylength is valid
+*/
+bool Keyed_Filter::valid_keylength(u32bit n) const
+ {
+ if(base_ptr)
+ return base_ptr->valid_keylength(n);
+ throw Invalid_State("Keyed_Filter::valid_keylength: No base algorithm set");
+ }
+
+}
diff --git a/botan/src/filters/basefilt.h b/botan/src/filters/basefilt.h
new file mode 100644
index 0000000..75625ab
--- /dev/null
+++ b/botan/src/filters/basefilt.h
@@ -0,0 +1,99 @@
+/*
+* Basic Filters
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_BASEFILT_H__
+#define BOTAN_BASEFILT_H__
+
+#include <botan/filter.h>
+#include <botan/sym_algo.h>
+
+namespace Botan {
+
+/**
+* This class represents Filter chains. A Filter chain is an ordered
+* concatenation of Filters, the input to a Chain sequentially passes
+* through all the Filters contained in the Chain.
+*/
+
+class BOTAN_DLL Chain : public Fanout_Filter
+ {
+ public:
+ void write(const byte input[], u32bit length) { send(input, length); }
+
+ /**
+ * Construct a chain of up to four filters. The filters are set
+ * up in the same order as the arguments.
+ */
+ Chain(Filter* = 0, Filter* = 0, Filter* = 0, Filter* = 0);
+
+ /**
+ * Construct a chain from range of filters
+ * @param filter_arr the list of filters
+ * @param length how many filters
+ */
+ Chain(Filter* filter_arr[], u32bit length);
+ };
+
+/**
+* This class represents a fork filter, whose purpose is to fork the
+* flow of data. It causes an input message to result in n messages at
+* the end of the filter, where n is the number of forks.
+*/
+class BOTAN_DLL Fork : public Fanout_Filter
+ {
+ public:
+ void write(const byte input[], u32bit length) { send(input, length); }
+ void set_port(u32bit n) { Fanout_Filter::set_port(n); }
+
+ /**
+ * Construct a Fork filter with up to four forks.
+ */
+ Fork(Filter*, Filter*, Filter* = 0, Filter* = 0);
+
+ /**
+ * Construct a Fork from range of filters
+ * @param filter_arr the list of filters
+ * @param length how many filters
+ */
+ Fork(Filter* filter_arr[], u32bit length);
+ };
+
+/**
+* This class represents keyed filters, i.e. filters that have to be
+* fed with a key in order to function.
+*/
+class BOTAN_DLL Keyed_Filter : public Filter
+ {
+ public:
+
+ /**
+ * Set the key of this filter.
+ * @param key the key to set
+ */
+ virtual void set_key(const SymmetricKey& key);
+
+ /**
+ * Set the initialization vector of this filter.
+ * @param iv the initialization vector to set
+ */
+ virtual void set_iv(const InitializationVector&) {}
+
+ /**
+ * Check whether a key length is valid for this filter.
+ * @param length the key length to be checked for validity
+ * @return true if the key length is valid, false otherwise
+ */
+ virtual bool valid_keylength(u32bit length) const;
+
+ Keyed_Filter() { base_ptr = 0; }
+ protected:
+ SymmetricAlgorithm* base_ptr;
+ };
+
+}
+
+#endif
diff --git a/botan/src/filters/buf_filt.cpp b/botan/src/filters/buf_filt.cpp
new file mode 100644
index 0000000..53352b5
--- /dev/null
+++ b/botan/src/filters/buf_filt.cpp
@@ -0,0 +1,71 @@
+/*
+* Buffering Filter
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/buf_filt.h>
+#include <botan/exceptn.h>
+#include <algorithm>
+
+namespace Botan {
+
+/*
+* Buffering_Filter Constructor
+*/
+Buffering_Filter::Buffering_Filter(u32bit b, u32bit i) : INITIAL_BLOCK_SIZE(i),
+ BLOCK_SIZE(b)
+ {
+ initial_block_pos = block_pos = 0;
+ initial.create(INITIAL_BLOCK_SIZE);
+ block.create(BLOCK_SIZE);
+ }
+
+/*
+* Reset the Buffering Filter
+*/
+void Buffering_Filter::end_msg()
+ {
+ if(initial_block_pos != INITIAL_BLOCK_SIZE)
+ throw Exception("Buffering_Filter: Not enough data for first block");
+ final_block(block, block_pos);
+ initial_block_pos = block_pos = 0;
+ initial.clear();
+ block.clear();
+ }
+
+/*
+* Buffer input into blocks
+*/
+void Buffering_Filter::write(const byte input[], u32bit length)
+ {
+ if(initial_block_pos != INITIAL_BLOCK_SIZE)
+ {
+ u32bit copied = std::min(INITIAL_BLOCK_SIZE - initial_block_pos, length);
+ initial.copy(initial_block_pos, input, copied);
+ input += copied;
+ length -= copied;
+ initial_block_pos += copied;
+ if(initial_block_pos == INITIAL_BLOCK_SIZE)
+ initial_block(initial);
+ }
+ block.copy(block_pos, input, length);
+ if(block_pos + length >= BLOCK_SIZE)
+ {
+ main_block(block);
+ input += (BLOCK_SIZE - block_pos);
+ length -= (BLOCK_SIZE - block_pos);
+ while(length >= BLOCK_SIZE)
+ {
+ main_block(input);
+ input += BLOCK_SIZE;
+ length -= BLOCK_SIZE;
+ }
+ block.copy(input, length);
+ block_pos = 0;
+ }
+ block_pos += length;
+ }
+
+}
diff --git a/botan/src/filters/buf_filt.h b/botan/src/filters/buf_filt.h
new file mode 100644
index 0000000..ce3dbc9
--- /dev/null
+++ b/botan/src/filters/buf_filt.h
@@ -0,0 +1,39 @@
+/*
+* Buffering Filter
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_BUFFERING_FILTER_H__
+#define BOTAN_BUFFERING_FILTER_H__
+
+#include <botan/filter.h>
+
+namespace Botan {
+
+/**
+* Buffering_Filter: This class represents filters for operations that
+* maintain an internal state.
+*/
+
+class BOTAN_DLL Buffering_Filter : public Filter
+ {
+ public:
+ void write(const byte[], u32bit);
+ virtual void end_msg();
+ Buffering_Filter(u32bit, u32bit = 0);
+ virtual ~Buffering_Filter() {}
+ protected:
+ virtual void initial_block(const byte[]) {}
+ virtual void main_block(const byte[]) = 0;
+ virtual void final_block(const byte[], u32bit) = 0;
+ private:
+ const u32bit INITIAL_BLOCK_SIZE, BLOCK_SIZE;
+ SecureVector<byte> initial, block;
+ u32bit initial_block_pos, block_pos;
+ };
+
+}
+
+#endif
diff --git a/botan/src/filters/data_snk.cpp b/botan/src/filters/data_snk.cpp
new file mode 100644
index 0000000..f8ee9f8
--- /dev/null
+++ b/botan/src/filters/data_snk.cpp
@@ -0,0 +1,62 @@
+/*
+* DataSink
+* (C) 1999-2007 Jack Lloyd
+* 2005 Matthew Gregan
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/data_snk.h>
+#include <botan/exceptn.h>
+#include <fstream>
+
+namespace Botan {
+
+/*
+* Write to a stream
+*/
+void DataSink_Stream::write(const byte out[], u32bit length)
+ {
+ sink->write(reinterpret_cast<const char*>(out), length);
+ if(!sink->good())
+ throw Stream_IO_Error("DataSink_Stream: Failure writing to " +
+ identifier);
+ }
+
+/*
+* DataSink_Stream Constructor
+*/
+DataSink_Stream::DataSink_Stream(std::ostream& out,
+ const std::string& name) :
+ identifier(name != "" ? name : "<std::ostream>"), owner(false)
+ {
+ sink = &out;
+ }
+
+/*
+* DataSink_Stream Constructor
+*/
+DataSink_Stream::DataSink_Stream(const std::string& path,
+ bool use_binary) :
+ identifier(path), owner(true)
+ {
+ if(use_binary)
+ sink = new std::ofstream(path.c_str(), std::ios::binary);
+ else
+ sink = new std::ofstream(path.c_str());
+
+ if(!sink->good())
+ throw Stream_IO_Error("DataSink_Stream: Failure opening " + path);
+ }
+
+/*
+* DataSink_Stream Destructor
+*/
+DataSink_Stream::~DataSink_Stream()
+ {
+ if(owner)
+ delete sink;
+ sink = 0;
+ }
+
+}
diff --git a/botan/src/filters/data_snk.h b/botan/src/filters/data_snk.h
new file mode 100644
index 0000000..61ddf6e
--- /dev/null
+++ b/botan/src/filters/data_snk.h
@@ -0,0 +1,65 @@
+/*
+* DataSink
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DATA_SINK_H__
+#define BOTAN_DATA_SINK_H__
+
+#include <botan/filter.h>
+#include <iosfwd>
+
+namespace Botan {
+
+/**
+* This class represents abstract data sink objects.
+*/
+class BOTAN_DLL DataSink : public Filter
+ {
+ public:
+ bool attachable() { return false; }
+ DataSink() {}
+ virtual ~DataSink() {}
+ private:
+ DataSink& operator=(const DataSink&) { return (*this); }
+ DataSink(const DataSink&);
+ };
+
+/**
+* This class represents a data sink which writes its output to a stream.
+*/
+class BOTAN_DLL DataSink_Stream : public DataSink
+ {
+ public:
+ void write(const byte[], u32bit);
+
+ /**
+ * Construct a DataSink_Stream from a stream.
+ * @param stream the stream to write to
+ * @param name identifier
+ */
+ DataSink_Stream(std::ostream& stream,
+ const std::string& name = "");
+
+ /**
+ * Construct a DataSink_Stream from a stream.
+ * @param file the name of the file to open a stream to
+ * @param use_binary indicates whether to treat the file
+ * as a binary file or not
+ */
+ DataSink_Stream(const std::string& filename,
+ bool use_binary = false);
+
+ ~DataSink_Stream();
+ private:
+ const std::string identifier;
+ const bool owner;
+
+ std::ostream* sink;
+ };
+
+}
+
+#endif
diff --git a/botan/src/filters/data_src.cpp b/botan/src/filters/data_src.cpp
new file mode 100644
index 0000000..e6387c4
--- /dev/null
+++ b/botan/src/filters/data_src.cpp
@@ -0,0 +1,207 @@
+/*
+* DataSource
+* (C) 1999-2007 Jack Lloyd
+* 2005 Matthew Gregan
+*
+* Distributed under the terms of the Botan license
+*/
+
+#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/botan/src/filters/data_src.h b/botan/src/filters/data_src.h
new file mode 100644
index 0000000..e16217e
--- /dev/null
+++ b/botan/src/filters/data_src.h
@@ -0,0 +1,150 @@
+/*
+* DataSource
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#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/botan/src/filters/fd_unix/fd_unix.cpp b/botan/src/filters/fd_unix/fd_unix.cpp
new file mode 100644
index 0000000..7f19b0a
--- /dev/null
+++ b/botan/src/filters/fd_unix/fd_unix.cpp
@@ -0,0 +1,53 @@
+/*
+* Pipe I/O for Unix
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/pipe.h>
+#include <botan/exceptn.h>
+#include <unistd.h>
+
+namespace Botan {
+
+/*
+* Write data from a pipe into a Unix fd
+*/
+int operator<<(int fd, Pipe& pipe)
+ {
+ SecureVector<byte> buffer(DEFAULT_BUFFERSIZE);
+ while(pipe.remaining())
+ {
+ u32bit got = pipe.read(buffer, buffer.size());
+ u32bit position = 0;
+ while(got)
+ {
+ ssize_t ret = write(fd, buffer + position, got);
+ if(ret == -1)
+ throw Stream_IO_Error("Pipe output operator (unixfd) has failed");
+ position += ret;
+ got -= ret;
+ }
+ }
+ return fd;
+ }
+
+/*
+* Read data from a Unix fd into a pipe
+*/
+int operator>>(int fd, Pipe& pipe)
+ {
+ SecureVector<byte> buffer(DEFAULT_BUFFERSIZE);
+ while(true)
+ {
+ ssize_t ret = read(fd, buffer, buffer.size());
+ if(ret == 0) break;
+ if(ret == -1)
+ throw Stream_IO_Error("Pipe input operator (unixfd) has failed");
+ pipe.write(buffer, ret);
+ }
+ return fd;
+ }
+
+}
diff --git a/botan/src/filters/fd_unix/fd_unix.h b/botan/src/filters/fd_unix/fd_unix.h
new file mode 100644
index 0000000..0aed009
--- /dev/null
+++ b/botan/src/filters/fd_unix/fd_unix.h
@@ -0,0 +1,23 @@
+/*
+* Pipe I/O for Unix
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PIPE_UNIXFD_H__
+#define BOTAN_PIPE_UNIXFD_H__
+
+#include <botan/pipe.h>
+
+namespace Botan {
+
+/*
+* Unix I/O Operators for Pipe
+*/
+int operator<<(int, Pipe&);
+int operator>>(int, Pipe&);
+
+}
+
+#endif
diff --git a/botan/src/filters/fd_unix/info.txt b/botan/src/filters/fd_unix/info.txt
new file mode 100644
index 0000000..d87978c
--- /dev/null
+++ b/botan/src/filters/fd_unix/info.txt
@@ -0,0 +1,28 @@
+realname "Unix I/O support for Pipe"
+
+define PIPE_UNIXFD_IO
+modset unix,beos
+
+load_on auto
+
+<add>
+fd_unix.h
+fd_unix.cpp
+</add>
+
+<os>
+aix
+beos
+cygwin
+darwin
+freebsd
+dragonfly
+hpux
+irix
+linux
+netbsd
+openbsd
+qnx
+solaris
+tru64
+</os>
diff --git a/botan/src/filters/filter.cpp b/botan/src/filters/filter.cpp
new file mode 100644
index 0000000..4bf0ef9
--- /dev/null
+++ b/botan/src/filters/filter.cpp
@@ -0,0 +1,127 @@
+/*
+* Filter
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/filter.h>
+#include <botan/secqueue.h>
+#include <botan/exceptn.h>
+
+namespace Botan {
+
+/*
+* Filter Constructor
+*/
+Filter::Filter()
+ {
+ next.resize(1);
+ port_num = 0;
+ filter_owns = 0;
+ owned = false;
+ }
+
+/*
+* Send data to all ports
+*/
+void Filter::send(const byte input[], u32bit length)
+ {
+ bool nothing_attached = true;
+ for(u32bit j = 0; j != total_ports(); ++j)
+ if(next[j])
+ {
+ if(write_queue.has_items())
+ next[j]->write(write_queue, write_queue.size());
+ next[j]->write(input, length);
+ nothing_attached = false;
+ }
+ if(nothing_attached)
+ write_queue.append(input, length);
+ else if(write_queue.has_items())
+ write_queue.destroy();
+ }
+
+/*
+* Start a new message
+*/
+void Filter::new_msg()
+ {
+ start_msg();
+ for(u32bit j = 0; j != total_ports(); ++j)
+ if(next[j])
+ next[j]->new_msg();
+ }
+
+/*
+* End the current message
+*/
+void Filter::finish_msg()
+ {
+ end_msg();
+ for(u32bit j = 0; j != total_ports(); ++j)
+ if(next[j])
+ next[j]->finish_msg();
+ }
+
+/*
+* Attach a filter to the current port
+*/
+void Filter::attach(Filter* new_filter)
+ {
+ if(new_filter)
+ {
+ Filter* last = this;
+ while(last->get_next())
+ last = last->get_next();
+ last->next[last->current_port()] = new_filter;
+ }
+ }
+
+/*
+* Set the active port on a filter
+*/
+void Filter::set_port(u32bit new_port)
+ {
+ if(new_port >= total_ports())
+ throw Invalid_Argument("Filter: Invalid port number");
+ port_num = new_port;
+ }
+
+/*
+* Return the next Filter in the logical chain
+*/
+Filter* Filter::get_next() const
+ {
+ if(port_num < next.size())
+ return next[port_num];
+ return 0;
+ }
+
+/*
+* Set the next Filters
+*/
+void Filter::set_next(Filter* filters[], u32bit size)
+ {
+ while(size && filters && filters[size-1] == 0)
+ --size;
+
+ next.clear();
+ next.resize(size);
+
+ port_num = 0;
+ filter_owns = 0;
+
+ for(u32bit j = 0; j != size; ++j)
+ next[j] = filters[j];
+ }
+
+/*
+* Return the total number of ports
+*/
+u32bit Filter::total_ports() const
+ {
+ return next.size();
+ }
+
+}
diff --git a/botan/src/filters/filter.h b/botan/src/filters/filter.h
new file mode 100644
index 0000000..b13a366
--- /dev/null
+++ b/botan/src/filters/filter.h
@@ -0,0 +1,113 @@
+/*
+* Filter
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_FILTER_H__
+#define BOTAN_FILTER_H__
+
+#include <botan/secmem.h>
+#include <vector>
+
+namespace Botan {
+
+/**
+* This class represents general abstract filter objects.
+*/
+class BOTAN_DLL Filter
+ {
+ public:
+
+ /**
+ * Write a portion of a message to this filter.
+ * @param input the input as a byte array
+ * @param length the length of the byte array input
+ */
+ virtual void write(const byte input[], u32bit length) = 0;
+
+ /**
+ * Start a new message. Must be closed by end_msg() before another
+ * message can be startet.
+ */
+ virtual void start_msg() {}
+
+ /**
+ * Tell the Filter that the current message shall be ended.
+ */
+ virtual void end_msg() {}
+
+ /**
+ * Check whether this filter is an attachable filter.
+ * @return true if this filter is attachable, false otherwise
+ */
+ virtual bool attachable() { return true; }
+
+ /**
+ * Start a new message in *this and all following filters. Only for
+ * internal use, not intended for use in client applications.
+ */
+ void new_msg();
+
+ /**
+ * End a new message in *this and all following filters. Only for
+ * internal use, not intended for use in client applications.
+ */
+ void finish_msg();
+
+ virtual ~Filter() {}
+ protected:
+ void send(const byte[], u32bit);
+ void send(byte input) { send(&input, 1); }
+ void send(const MemoryRegion<byte>& in) { send(in.begin(), in.size()); }
+ Filter();
+ private:
+ Filter(const Filter&) {}
+ Filter& operator=(const Filter&) { return (*this); }
+
+ friend class Pipe;
+ friend class Fanout_Filter;
+
+ u32bit total_ports() const;
+ u32bit current_port() const { return port_num; }
+ void set_port(u32bit);
+
+ u32bit owns() const { return filter_owns; }
+
+ void attach(Filter*);
+ void set_next(Filter*[], u32bit);
+ Filter* get_next() const;
+
+ SecureVector<byte> write_queue;
+ std::vector<Filter*> next;
+ u32bit port_num, filter_owns;
+
+ // true if filter belongs to a pipe --> prohibit filter sharing!
+ bool owned;
+ };
+
+/**
+* This is the abstract Fanout_Filter base class.
+**/
+class BOTAN_DLL Fanout_Filter : public Filter
+ {
+ protected:
+ void incr_owns() { ++filter_owns; }
+
+ void set_port(u32bit n) { Filter::set_port(n); }
+ void set_next(Filter* f[], u32bit n) { Filter::set_next(f, n); }
+ void attach(Filter* f) { Filter::attach(f); }
+ };
+
+/**
+* The type of checking to be performed by decoders:
+* NONE - no checks, IGNORE_WS - perform checks, but ignore
+* whitespaces, FULL_CHECK - perform checks, also complain
+* about white spaces.
+*/
+enum Decoder_Checking { NONE, IGNORE_WS, FULL_CHECK };
+
+}
+
+#endif
diff --git a/botan/src/filters/filters.h b/botan/src/filters/filters.h
new file mode 100644
index 0000000..725651f
--- /dev/null
+++ b/botan/src/filters/filters.h
@@ -0,0 +1,189 @@
+/*
+* Filters
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_FILTERS_H__
+#define BOTAN_FILTERS_H__
+
+#include <botan/block_cipher.h>
+#include <botan/stream_cipher.h>
+#include <botan/hash.h>
+#include <botan/mac.h>
+
+#include <botan/pipe.h>
+#include <botan/basefilt.h>
+#include <botan/data_snk.h>
+#include <botan/scan_name.h>
+
+#if defined(BOTAN_HAS_BASE64_CODEC)
+ #include <botan/base64.h>
+#endif
+
+#if defined(BOTAN_HAS_HEX_CODEC)
+ #include <botan/hex.h>
+#endif
+
+namespace Botan {
+
+/**
+* Stream Cipher Filter.
+*/
+class BOTAN_DLL StreamCipher_Filter : public Keyed_Filter
+ {
+ public:
+
+ /**
+ * Seek in the stream.
+ * @param position the position to seek ahead
+ */
+ void seek(u32bit position) { cipher->seek(position); }
+
+ /**
+ * Find out whether the cipher underlying this filter supports
+ * resyncing.
+ * @return true if the cipher supports resyncing
+ */
+ bool supports_resync() const { return (cipher->IV_LENGTH != 0); }
+
+ /**
+ * Set the initialization vector for this filter.
+ * @param iv the initialization vector to set
+ */
+ void set_iv(const InitializationVector& iv);
+ void write(const byte[], u32bit);
+
+ /**
+ * Construct a stream cipher filter.
+ * @param cipher_obj a cipher object to use
+ */
+ StreamCipher_Filter(StreamCipher* cipher_obj);
+
+ /**
+ * Construct a stream cipher filter.
+ * @param cipher the name of the desired cipher
+ */
+ StreamCipher_Filter(const std::string& cipher);
+
+ /**
+ * Construct a stream cipher filter.
+ * @param cipher the name of the desired cipher
+ * @param key the key to use inside this filter
+ */
+ StreamCipher_Filter(const std::string& cipher, const SymmetricKey& key);
+
+ ~StreamCipher_Filter() { delete cipher; }
+ private:
+ SecureVector<byte> buffer;
+ StreamCipher* cipher;
+ };
+
+/**
+* Hash Filter.
+*/
+class BOTAN_DLL Hash_Filter : public Filter
+ {
+ public:
+ void write(const byte input[], u32bit len) { hash->update(input, len); }
+ void end_msg();
+
+ /**
+ * Construct a hash filter.
+ * @param hash_fun the hash function to use
+ * @param len the output length of this filter. Leave the default
+ * value 0 if you want to use the full output of the hashfunction
+ * hash. Otherwise, specify a smaller value here so that the
+ * output of the hash algorithm will be cut off.
+ */
+ Hash_Filter(HashFunction* hash_fun, u32bit len = 0) :
+ OUTPUT_LENGTH(len), hash(hash_fun) {}
+
+ /**
+ * Construct a hash filter.
+ * @param request the name of the hash algorithm to use
+ * @param len the output length of this filter. Leave the default
+ * value 0 if you want to use the full output of the hashfunction
+ * hash. Otherwise, specify a smaller value here so that the
+ * output of the hash algorithm will be cut off.
+ */
+ Hash_Filter(const std::string& request, u32bit len = 0);
+
+ ~Hash_Filter() { delete hash; }
+ private:
+ const u32bit OUTPUT_LENGTH;
+ HashFunction* hash;
+ };
+
+/**
+* MessageAuthenticationCode Filter.
+*/
+class BOTAN_DLL MAC_Filter : public Keyed_Filter
+ {
+ public:
+ void write(const byte input[], u32bit len) { mac->update(input, len); }
+ void end_msg();
+
+ /**
+ * Construct a MAC filter. The MAC key will be left empty.
+ * @param mac the MAC to use
+ * @param len the output length of this filter. Leave the default
+ * value 0 if you want to use the full output of the
+ * MAC. Otherwise, specify a smaller value here so that the
+ * output of the MAC will be cut off.
+ */
+ MAC_Filter(MessageAuthenticationCode* mac_obj,
+ u32bit out_len = 0) : OUTPUT_LENGTH(out_len)
+ {
+ base_ptr = mac = mac_obj;
+ }
+
+ /**
+ * Construct a MAC filter.
+ * @param mac the MAC to use
+ * @param key the MAC key to use
+ * @param len the output length of this filter. Leave the default
+ * value 0 if you want to use the full output of the
+ * MAC. Otherwise, specify a smaller value here so that the
+ * output of the MAC will be cut off.
+ */
+ MAC_Filter(MessageAuthenticationCode* mac_obj,
+ const SymmetricKey& key,
+ u32bit out_len = 0) : OUTPUT_LENGTH(out_len)
+ {
+ base_ptr = mac = mac_obj;
+ mac->set_key(key);
+ }
+
+ /**
+ * Construct a MAC filter. The MAC key will be left empty.
+ * @param mac the name of the MAC to use
+ * @param len the output length of this filter. Leave the default
+ * value 0 if you want to use the full output of the
+ * MAC. Otherwise, specify a smaller value here so that the
+ * output of the MAC will be cut off.
+ */
+ MAC_Filter(const std::string& mac, u32bit len = 0);
+
+ /**
+ * Construct a MAC filter.
+ * @param mac the name of the MAC to use
+ * @param key the MAC key to use
+ * @param len the output length of this filter. Leave the default
+ * value 0 if you want to use the full output of the
+ * MAC. Otherwise, specify a smaller value here so that the
+ * output of the MAC will be cut off.
+ */
+ MAC_Filter(const std::string& mac, const SymmetricKey& key,
+ u32bit len = 0);
+
+ ~MAC_Filter() { delete mac; }
+ private:
+ const u32bit OUTPUT_LENGTH;
+ MessageAuthenticationCode* mac;
+ };
+
+}
+
+#endif
diff --git a/botan/src/filters/info.txt b/botan/src/filters/info.txt
new file mode 100644
index 0000000..79a92a9
--- /dev/null
+++ b/botan/src/filters/info.txt
@@ -0,0 +1,41 @@
+realname "Pipe/Filter"
+
+load_on auto
+
+define FILTERS
+
+<add>
+algo_filt.cpp
+basefilt.cpp
+basefilt.h
+buf_filt.cpp
+buf_filt.h
+data_snk.cpp
+data_snk.h
+data_src.cpp
+data_src.h
+filter.cpp
+filter.h
+filters.h
+out_buf.cpp
+out_buf.h
+pbe.h
+pipe.cpp
+pipe.h
+pipe_io.cpp
+pipe_rw.cpp
+secqueue.cpp
+secqueue.h
+</add>
+
+<requires>
+alloc
+asn1
+block
+hash
+libstate
+mac
+rng
+stream
+sym_algo
+</requires>
diff --git a/botan/src/filters/out_buf.cpp b/botan/src/filters/out_buf.cpp
new file mode 100644
index 0000000..6002f4f
--- /dev/null
+++ b/botan/src/filters/out_buf.cpp
@@ -0,0 +1,119 @@
+/*
+* Pipe Output Buffer Source file
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/out_buf.h>
+#include <botan/secqueue.h>
+
+namespace Botan {
+
+/*
+* Read data from a message
+*/
+u32bit Output_Buffers::read(byte output[], u32bit length,
+ Pipe::message_id msg)
+ {
+ SecureQueue* q = get(msg);
+ if(q)
+ return q->read(output, length);
+ return 0;
+ }
+
+/*
+* Peek at data in a message
+*/
+u32bit Output_Buffers::peek(byte output[], u32bit length,
+ u32bit stream_offset,
+ Pipe::message_id msg) const
+ {
+ SecureQueue* q = get(msg);
+ if(q)
+ return q->peek(output, length, stream_offset);
+ return 0;
+ }
+
+/*
+* Check available bytes in a message
+*/
+u32bit Output_Buffers::remaining(Pipe::message_id msg) const
+ {
+ SecureQueue* q = get(msg);
+ if(q)
+ return q->size();
+ return 0;
+ }
+
+/*
+* Add a new output queue
+*/
+void Output_Buffers::add(SecureQueue* queue)
+ {
+ if(!queue)
+ throw Internal_Error("Output_Buffers::add: Argument was NULL");
+
+ if(buffers.size() == buffers.max_size())
+ throw Internal_Error("Output_Buffers::add: No more room in container");
+
+ buffers.push_back(queue);
+ }
+
+/*
+* Retire old output queues
+*/
+void Output_Buffers::retire()
+ {
+ while(buffers.size())
+ {
+ if(buffers[0] == 0 || buffers[0]->size() == 0)
+ {
+ delete buffers[0];
+ buffers.pop_front();
+ offset = offset + Pipe::message_id(1);
+ }
+ else
+ break;
+ }
+ }
+
+/*
+* Get a particular output queue
+*/
+SecureQueue* Output_Buffers::get(Pipe::message_id msg) const
+ {
+ if(msg < offset)
+ return 0;
+ if(msg > message_count())
+ throw Internal_Error("Output_Buffers::get: msg > size");
+
+ return buffers[msg-offset];
+ }
+
+/*
+* Return the total number of messages
+*/
+Pipe::message_id Output_Buffers::message_count() const
+ {
+ return (offset + buffers.size());
+ }
+
+/*
+* Output_Buffers Constructor
+*/
+Output_Buffers::Output_Buffers()
+ {
+ offset = 0;
+ }
+
+/*
+* Output_Buffers Destructor
+*/
+Output_Buffers::~Output_Buffers()
+ {
+ for(u32bit j = 0; j != buffers.size(); ++j)
+ delete buffers[j];
+ }
+
+}
diff --git a/botan/src/filters/out_buf.h b/botan/src/filters/out_buf.h
new file mode 100644
index 0000000..0baacda
--- /dev/null
+++ b/botan/src/filters/out_buf.h
@@ -0,0 +1,43 @@
+/*
+* Output Buffer
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_OUTPUT_BUFFER_H__
+#define BOTAN_OUTPUT_BUFFER_H__
+
+#include <botan/types.h>
+#include <botan/pipe.h>
+#include <deque>
+
+namespace Botan {
+
+/*
+* Container of output buffers for Pipe
+*/
+class BOTAN_DLL Output_Buffers
+ {
+ public:
+ u32bit read(byte[], u32bit, Pipe::message_id);
+ u32bit peek(byte[], u32bit, u32bit, Pipe::message_id) const;
+ u32bit remaining(Pipe::message_id) const;
+
+ void add(class SecureQueue*);
+ void retire();
+
+ Pipe::message_id message_count() const;
+
+ Output_Buffers();
+ ~Output_Buffers();
+ private:
+ class SecureQueue* get(Pipe::message_id) const;
+
+ std::deque<SecureQueue*> buffers;
+ Pipe::message_id offset;
+ };
+
+}
+
+#endif
diff --git a/botan/src/filters/pbe.h b/botan/src/filters/pbe.h
new file mode 100644
index 0000000..f06d593
--- /dev/null
+++ b/botan/src/filters/pbe.h
@@ -0,0 +1,56 @@
+/*
+* PBE
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PBE_BASE_H__
+#define BOTAN_PBE_BASE_H__
+
+#include <botan/asn1_oid.h>
+#include <botan/data_src.h>
+#include <botan/filter.h>
+#include <botan/rng.h>
+
+namespace Botan {
+
+/**
+* Password Based Encryption (PBE) Filter.
+*/
+class BOTAN_DLL PBE : public Filter
+ {
+ public:
+ /**
+ * Set this filter's key.
+ * @param pw the password to be used for the encryption
+ */
+ virtual void set_key(const std::string&) = 0;
+
+ /**
+ * Create a new random salt value and set the default iterations value.
+ */
+ virtual void new_params(RandomNumberGenerator& rng) = 0;
+
+ /**
+ * DER encode the params (the number of iterations and the salt value)
+ * @return the encoded params
+ */
+ virtual MemoryVector<byte> encode_params() const = 0;
+
+ /**
+ * Decode params and use them inside this Filter.
+ * @param src a data source to read the encoded params from
+ */
+ virtual void decode_params(DataSource&) = 0;
+
+ /**
+ * Get this PBE's OID.
+ * @return the OID
+ */
+ virtual OID get_oid() const = 0;
+ };
+
+}
+
+#endif
diff --git a/botan/src/filters/pipe.cpp b/botan/src/filters/pipe.cpp
new file mode 100644
index 0000000..33824be
--- /dev/null
+++ b/botan/src/filters/pipe.cpp
@@ -0,0 +1,306 @@
+/*
+* Pipe
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/pipe.h>
+#include <botan/out_buf.h>
+#include <botan/secqueue.h>
+#include <botan/parsing.h>
+
+namespace Botan {
+
+/*
+* Constructor for Invalid_Message_Number
+*/
+Pipe::Invalid_Message_Number::Invalid_Message_Number(const std::string& where,
+ message_id msg)
+ {
+ set_msg("Pipe::" + where + ": Invalid message number " +
+ to_string(msg));
+ }
+
+namespace {
+
+/*
+* A Filter that does nothing
+*/
+class Null_Filter : public Filter
+ {
+ public:
+ void write(const byte input[], u32bit length)
+ { send(input, length); }
+ };
+
+}
+
+/*
+* Pipe Constructor
+*/
+Pipe::Pipe(Filter* f1, Filter* f2, Filter* f3, Filter* f4)
+ {
+ init();
+ append(f1);
+ append(f2);
+ append(f3);
+ append(f4);
+ }
+
+/*
+* Pipe Constructor
+*/
+Pipe::Pipe(Filter* filter_array[], u32bit count)
+ {
+ init();
+ for(u32bit j = 0; j != count; ++j)
+ append(filter_array[j]);
+ }
+
+/*
+* Pipe Destructor
+*/
+Pipe::~Pipe()
+ {
+ destruct(pipe);
+ delete outputs;
+ }
+
+/*
+* Initialize the Pipe
+*/
+void Pipe::init()
+ {
+ outputs = new Output_Buffers;
+ pipe = 0;
+ default_read = 0;
+ inside_msg = false;
+ }
+
+/*
+* Reset the Pipe
+*/
+void Pipe::reset()
+ {
+ if(inside_msg)
+ throw Invalid_State("Pipe cannot be reset while it is processing");
+ destruct(pipe);
+ pipe = 0;
+ inside_msg = false;
+ }
+
+/*
+* Destroy the Pipe
+*/
+void Pipe::destruct(Filter* to_kill)
+ {
+ if(!to_kill || dynamic_cast<SecureQueue*>(to_kill))
+ return;
+ for(u32bit j = 0; j != to_kill->total_ports(); ++j)
+ destruct(to_kill->next[j]);
+ delete to_kill;
+ }
+
+/*
+* Test if the Pipe has any data in it
+*/
+bool Pipe::end_of_data() const
+ {
+ return (remaining() == 0);
+ }
+
+/*
+* Set the default read message
+*/
+void Pipe::set_default_msg(message_id msg)
+ {
+ if(msg >= message_count())
+ throw Invalid_Argument("Pipe::set_default_msg: msg number is too high");
+ default_read = msg;
+ }
+
+/*
+* Process a full message at once
+*/
+void Pipe::process_msg(const byte input[], u32bit length)
+ {
+ start_msg();
+ write(input, length);
+ end_msg();
+ }
+
+/*
+* Process a full message at once
+*/
+void Pipe::process_msg(const MemoryRegion<byte>& input)
+ {
+ process_msg(input.begin(), input.size());
+ }
+
+/*
+* Process a full message at once
+*/
+void Pipe::process_msg(const std::string& input)
+ {
+ process_msg(reinterpret_cast<const byte*>(input.data()), input.length());
+ }
+
+/*
+* Process a full message at once
+*/
+void Pipe::process_msg(DataSource& input)
+ {
+ start_msg();
+ write(input);
+ end_msg();
+ }
+
+/*
+* Start a new message
+*/
+void Pipe::start_msg()
+ {
+ if(inside_msg)
+ throw Invalid_State("Pipe::start_msg: Message was already started");
+ if(pipe == 0)
+ pipe = new Null_Filter;
+ find_endpoints(pipe);
+ pipe->new_msg();
+ inside_msg = true;
+ }
+
+/*
+* End the current message
+*/
+void Pipe::end_msg()
+ {
+ if(!inside_msg)
+ throw Invalid_State("Pipe::end_msg: Message was already ended");
+ pipe->finish_msg();
+ clear_endpoints(pipe);
+ if(dynamic_cast<Null_Filter*>(pipe))
+ {
+ delete pipe;
+ pipe = 0;
+ }
+ inside_msg = false;
+
+ outputs->retire();
+ }
+
+/*
+* Find the endpoints of the Pipe
+*/
+void Pipe::find_endpoints(Filter* f)
+ {
+ for(u32bit j = 0; j != f->total_ports(); ++j)
+ if(f->next[j] && !dynamic_cast<SecureQueue*>(f->next[j]))
+ find_endpoints(f->next[j]);
+ else
+ {
+ SecureQueue* q = new SecureQueue;
+ f->next[j] = q;
+ outputs->add(q);
+ }
+ }
+
+/*
+* Remove the SecureQueues attached to the Filter
+*/
+void Pipe::clear_endpoints(Filter* f)
+ {
+ if(!f) return;
+ for(u32bit j = 0; j != f->total_ports(); ++j)
+ {
+ if(f->next[j] && dynamic_cast<SecureQueue*>(f->next[j]))
+ f->next[j] = 0;
+ clear_endpoints(f->next[j]);
+ }
+ }
+
+/*
+* Append a Filter to the Pipe
+*/
+void Pipe::append(Filter* filter)
+ {
+ if(inside_msg)
+ throw Invalid_State("Cannot append to a Pipe while it is processing");
+ if(!filter)
+ return;
+ if(dynamic_cast<SecureQueue*>(filter))
+ throw Invalid_Argument("Pipe::append: SecureQueue cannot be used");
+ if(filter->owned)
+ throw Invalid_Argument("Filters cannot be shared among multiple Pipes");
+
+ filter->owned = true;
+
+ if(!pipe) pipe = filter;
+ else pipe->attach(filter);
+ }
+
+/*
+* Prepend a Filter to the Pipe
+*/
+void Pipe::prepend(Filter* filter)
+ {
+ if(inside_msg)
+ throw Invalid_State("Cannot prepend to a Pipe while it is processing");
+ if(!filter)
+ return;
+ if(dynamic_cast<SecureQueue*>(filter))
+ throw Invalid_Argument("Pipe::prepend: SecureQueue cannot be used");
+ if(filter->owned)
+ throw Invalid_Argument("Filters cannot be shared among multiple Pipes");
+
+ filter->owned = true;
+
+ if(pipe) filter->attach(pipe);
+ pipe = filter;
+ }
+
+/*
+* Pop a Filter off the Pipe
+*/
+void Pipe::pop()
+ {
+ if(inside_msg)
+ throw Invalid_State("Cannot pop off a Pipe while it is processing");
+
+ if(!pipe)
+ return;
+
+ if(pipe->total_ports() > 1)
+ throw Invalid_State("Cannot pop off a Filter with multiple ports");
+
+ Filter* f = pipe;
+ u32bit owns = f->owns();
+ pipe = pipe->next[0];
+ delete f;
+
+ while(owns--)
+ {
+ f = pipe;
+ pipe = pipe->next[0];
+ delete f;
+ }
+ }
+
+/*
+* Return the number of messages in this Pipe
+*/
+Pipe::message_id Pipe::message_count() const
+ {
+ return outputs->message_count();
+ }
+
+/*
+* Static Member Variables
+*/
+const Pipe::message_id Pipe::LAST_MESSAGE =
+ static_cast<Pipe::message_id>(-2);
+
+const Pipe::message_id Pipe::DEFAULT_MESSAGE =
+ static_cast<Pipe::message_id>(-1);
+
+}
diff --git a/botan/src/filters/pipe.h b/botan/src/filters/pipe.h
new file mode 100644
index 0000000..120f2fb
--- /dev/null
+++ b/botan/src/filters/pipe.h
@@ -0,0 +1,275 @@
+/*
+* Pipe
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PIPE_H__
+#define BOTAN_PIPE_H__
+
+#include <botan/data_src.h>
+#include <botan/filter.h>
+#include <botan/exceptn.h>
+#include <iosfwd>
+
+namespace Botan {
+
+/**
+* This class represents pipe objects.
+* A set of filters can be placed into a pipe, and information flows
+* through the pipe until it reaches the end, where the output is
+* collected for retrieval. If you're familiar with the Unix shell
+* environment, this design will sound quite familiar.
+*/
+
+class BOTAN_DLL Pipe : public DataSource
+ {
+ public:
+ typedef u32bit message_id;
+
+ class Invalid_Message_Number : public Invalid_Argument
+ {
+ public:
+ Invalid_Message_Number(const std::string&, message_id);
+ };
+
+ static const message_id LAST_MESSAGE;
+ static const message_id DEFAULT_MESSAGE;
+
+ /**
+ * Write input to the pipe, i.e. to its first filter.
+ * @param in the byte array to write
+ * @param length the length of the byte array in
+ */
+ void write(const byte in[], u32bit length);
+
+ /**
+ * Write input to the pipe, i.e. to its first filter.
+ * @param in the MemoryRegion containing the data to write
+ */
+ void write(const MemoryRegion<byte>& in);
+
+ /**
+ * Write input to the pipe, i.e. to its first filter.
+ * @param in the string containing the data to write
+ */
+ void write(const std::string& in);
+
+ /**
+ * Write input to the pipe, i.e. to its first filter.
+ * @param in the DataSource to read the data from
+ */
+ void write(DataSource& in);
+
+ /**
+ * Write input to the pipe, i.e. to its first filter.
+ * @param in a single byte to be written
+ */
+ void write(byte in);
+
+ /**
+ * Perform start_msg(), write() and end_msg() sequentially.
+ * @param in the byte array containing the data to write
+ * @param length the length of the byte array to write
+ */
+ void process_msg(const byte in[], u32bit length);
+
+ /**
+ * Perform start_msg(), write() and end_msg() sequentially.
+ * @param in the MemoryRegion containing the data to write
+ */
+ void process_msg(const MemoryRegion<byte>& in);
+
+ /**
+ * Perform start_msg(), write() and end_msg() sequentially.
+ * @param in the string containing the data to write
+ */
+ void process_msg(const std::string& in);
+
+ /**
+ * Perform start_msg(), write() and end_msg() sequentially.
+ * @param in the DataSource providing the data to write
+ */
+ void process_msg(DataSource& in);
+
+ /**
+ * Find out how many bytes are ready to read.
+ * @param msg the number identifying the message
+ * for which the information is desired
+ * @return the number of bytes that can still be read
+ */
+ u32bit remaining(message_id msg = DEFAULT_MESSAGE) const;
+
+ /**
+ * Read the default message from the pipe. Moves the internal
+ * offset so that every call to read will return a new portion of
+ * the message.
+ * @param output the byte array to write the read bytes to
+ * @param length the length of the byte array output
+ * @return the number of bytes actually read into output
+ */
+ u32bit read(byte output[], u32bit length);
+
+ /**
+ * Read a specified message from the pipe. Moves the internal
+ * offset so that every call to read will return a new portion of
+ * the message.
+ * @param output the byte array to write the read bytes to
+ * @param length the length of the byte array output
+ * @param msg the number identifying the message to read from
+ * @return the number of bytes actually read into output
+ */
+ u32bit read(byte output[], u32bit length, message_id msg);
+
+ /**
+ * Read a single byte from the pipe. Moves the internal offset so that
+ * every call to read will return a new portion of the message.
+ * @param output the byte to write the result to
+ * @return the number of bytes actually read into output
+ */
+ u32bit read(byte& output, message_id msg = DEFAULT_MESSAGE);
+
+ /**
+ * Read the full contents of the pipe.
+ * @param msg the number identifying the message to read from
+ * @return a SecureVector holding the contents of the pipe
+ */
+ SecureVector<byte> read_all(message_id msg = DEFAULT_MESSAGE);
+
+ /**
+ * Read the full contents of the pipe.
+ * @param msg the number identifying the message to read from
+ * @return a string holding the contents of the pipe
+ */
+ std::string read_all_as_string(message_id = DEFAULT_MESSAGE);
+
+ /** Read from the default message but do not modify the internal
+ * offset. Consecutive calls to peek() will return portions of
+ * the message starting at the same position.
+ * @param output the byte array to write the peeked message part to
+ * @param length the length of the byte array output
+ * @param offset the offset from the current position in message
+ * @return the number of bytes actually peeked and written into output
+ */
+ u32bit peek(byte output[], u32bit length, u32bit offset) const;
+
+ /** Read from the specified message but do not modify the
+ * internal offset. Consecutive calls to peek() will return
+ * portions of the message starting at the same position.
+ * @param output the byte array to write the peeked message part to
+ * @param length the length of the byte array output
+ * @param offset the offset from the current position in message
+ * @param msg the number identifying the message to peek from
+ * @return the number of bytes actually peeked and written into output
+ */
+ u32bit peek(byte output[], u32bit length,
+ u32bit offset, message_id msg) const;
+
+ /** Read a single byte from the specified message but do not
+ * modify the internal offset. Consecutive calls to peek() will
+ * return portions of the message starting at the same position.
+ * @param output the byte to write the peeked message byte to
+ * @param offset the offset from the current position in message
+ * @param msg the number identifying the message to peek from
+ * @return the number of bytes actually peeked and written into output
+ */
+ u32bit peek(byte& output, u32bit offset,
+ message_id msg = DEFAULT_MESSAGE) const;
+
+ u32bit default_msg() const { return default_read; }
+
+ /**
+ * Set the default message
+ * @param msg the number identifying the message which is going to
+ * be the new default message
+ */
+ void set_default_msg(message_id msg);
+
+ /**
+ * Get the number of messages the are in this pipe.
+ * @return the number of messages the are in this pipe
+ */
+ message_id message_count() const;
+
+ /**
+ * Test whether this pipe has any data that can be read from.
+ * @return true if there is more data to read, false otherwise
+ */
+ bool end_of_data() const;
+
+ /**
+ * Start a new message in the pipe. A potential other message in this pipe
+ * must be closed with end_msg() before this function may be called.
+ */
+ void start_msg();
+
+ /**
+ * End the current message.
+ */
+ void end_msg();
+
+ /**
+ * Insert a new filter at the front of the pipe
+ * @param filt the new filter to insert
+ */
+ void prepend(Filter* filt);
+
+ /**
+ * Insert a new filter at the back of the pipe
+ * @param filt the new filter to insert
+ */
+ void append(Filter* filt);
+
+ /**
+ * Remove the first filter at the front of the pipe.
+ */
+ void pop();
+
+ /**
+ * Reset this pipe to an empty pipe.
+ */
+ void reset();
+
+ /**
+ * Construct a Pipe of up to four filters. The filters are set up
+ * in the same order as the arguments.
+ */
+ Pipe(Filter* = 0, Filter* = 0, Filter* = 0, Filter* = 0);
+
+ /**
+ * Construct a Pipe from range of filters passed as an array
+ * @param filters the set of filters to use
+ * @param count the number of elements in filters
+ */
+ Pipe(Filter* filters[], u32bit count);
+ ~Pipe();
+ private:
+ Pipe(const Pipe&) : DataSource() {}
+ Pipe& operator=(const Pipe&) { return (*this); }
+ void init();
+ void destruct(Filter*);
+ void find_endpoints(Filter*);
+ void clear_endpoints(Filter*);
+
+ message_id get_message_no(const std::string&, message_id) const;
+
+ Filter* pipe;
+ class Output_Buffers* outputs;
+ message_id default_read;
+ bool inside_msg;
+ };
+
+/*
+* I/O Operators for Pipe
+*/
+BOTAN_DLL std::ostream& operator<<(std::ostream&, Pipe&);
+BOTAN_DLL std::istream& operator>>(std::istream&, Pipe&);
+
+}
+
+#endif
+
+#if defined(BOTAN_HAS_PIPE_UNIXFD_IO)
+ #include <botan/fd_unix.h>
+#endif
diff --git a/botan/src/filters/pipe_io.cpp b/botan/src/filters/pipe_io.cpp
new file mode 100644
index 0000000..c57be6d
--- /dev/null
+++ b/botan/src/filters/pipe_io.cpp
@@ -0,0 +1,45 @@
+/*
+* Pipe I/O
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/pipe.h>
+#include <iostream>
+
+namespace Botan {
+
+/*
+* Write data from a pipe into an ostream
+*/
+std::ostream& operator<<(std::ostream& stream, Pipe& pipe)
+ {
+ SecureVector<byte> buffer(DEFAULT_BUFFERSIZE);
+ while(stream.good() && pipe.remaining())
+ {
+ u32bit got = pipe.read(buffer, buffer.size());
+ stream.write(reinterpret_cast<const char*>(buffer.begin()), got);
+ }
+ if(!stream.good())
+ throw Stream_IO_Error("Pipe output operator (iostream) has failed");
+ return stream;
+ }
+
+/*
+* Read data from an istream into a pipe
+*/
+std::istream& operator>>(std::istream& stream, Pipe& pipe)
+ {
+ SecureVector<byte> buffer(DEFAULT_BUFFERSIZE);
+ while(stream.good())
+ {
+ stream.read(reinterpret_cast<char*>(buffer.begin()), buffer.size());
+ pipe.write(buffer, stream.gcount());
+ }
+ if(stream.bad() || (stream.fail() && !stream.eof()))
+ throw Stream_IO_Error("Pipe input operator (iostream) has failed");
+ return stream;
+ }
+
+}
diff --git a/botan/src/filters/pipe_rw.cpp b/botan/src/filters/pipe_rw.cpp
new file mode 100644
index 0000000..41b57a7
--- /dev/null
+++ b/botan/src/filters/pipe_rw.cpp
@@ -0,0 +1,167 @@
+/*
+* Pipe Reading/Writing
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/pipe.h>
+#include <botan/out_buf.h>
+#include <botan/secqueue.h>
+
+namespace Botan {
+
+/*
+* Look up the canonical ID for a queue
+*/
+Pipe::message_id Pipe::get_message_no(const std::string& func_name,
+ message_id msg) const
+ {
+ if(msg == DEFAULT_MESSAGE)
+ msg = default_msg();
+ else if(msg == LAST_MESSAGE)
+ msg = message_count() - 1;
+
+ if(msg >= message_count())
+ throw Invalid_Message_Number(func_name, msg);
+
+ return msg;
+ }
+
+/*
+* Write into a Pipe
+*/
+void Pipe::write(const byte input[], u32bit length)
+ {
+ if(!inside_msg)
+ throw Exception("Cannot write to a Pipe while it is not processing");
+ pipe->write(input, length);
+ }
+
+/*
+* Write into a Pipe
+*/
+void Pipe::write(const MemoryRegion<byte>& input)
+ {
+ write(input.begin(), input.size());
+ }
+
+/*
+* Write a string into a Pipe
+*/
+void Pipe::write(const std::string& str)
+ {
+ write(reinterpret_cast<const byte*>(str.data()), str.size());
+ }
+
+/*
+* Write a single byte into a Pipe
+*/
+void Pipe::write(byte input)
+ {
+ write(&input, 1);
+ }
+
+/*
+* Write the contents of a DataSource into a Pipe
+*/
+void Pipe::write(DataSource& source)
+ {
+ SecureVector<byte> buffer(DEFAULT_BUFFERSIZE);
+ while(!source.end_of_data())
+ {
+ u32bit got = source.read(buffer, buffer.size());
+ write(buffer, got);
+ }
+ }
+
+/*
+* Read some data from the pipe
+*/
+u32bit Pipe::read(byte output[], u32bit length, message_id msg)
+ {
+ return outputs->read(output, length, get_message_no("read", msg));
+ }
+
+/*
+* Read some data from the pipe
+*/
+u32bit Pipe::read(byte output[], u32bit length)
+ {
+ return read(output, length, DEFAULT_MESSAGE);
+ }
+
+/*
+* Read a single byte from the pipe
+*/
+u32bit Pipe::read(byte& out, message_id msg)
+ {
+ return read(&out, 1, msg);
+ }
+
+/*
+* Return all data in the pipe
+*/
+SecureVector<byte> Pipe::read_all(message_id msg)
+ {
+ msg = ((msg != DEFAULT_MESSAGE) ? msg : default_msg());
+ SecureVector<byte> buffer(remaining(msg));
+ read(buffer, buffer.size(), msg);
+ return buffer;
+ }
+
+/*
+* Return all data in the pipe as a string
+*/
+std::string Pipe::read_all_as_string(message_id msg)
+ {
+ msg = ((msg != DEFAULT_MESSAGE) ? msg : default_msg());
+ SecureVector<byte> buffer(DEFAULT_BUFFERSIZE);
+ std::string str;
+ str.reserve(remaining(msg));
+
+ while(true)
+ {
+ u32bit got = read(buffer, buffer.size(), msg);
+ if(got == 0)
+ break;
+ str.append(reinterpret_cast<const char*>(buffer.begin()), got);
+ }
+
+ return str;
+ }
+
+/*
+* Find out how many bytes are ready to read
+*/
+u32bit Pipe::remaining(message_id msg) const
+ {
+ return outputs->remaining(get_message_no("remaining", msg));
+ }
+
+/*
+* Peek at some data in the pipe
+*/
+u32bit Pipe::peek(byte output[], u32bit length,
+ u32bit offset, message_id msg) const
+ {
+ return outputs->peek(output, length, offset, get_message_no("peek", msg));
+ }
+
+/*
+* Peek at some data in the pipe
+*/
+u32bit Pipe::peek(byte output[], u32bit length, u32bit offset) const
+ {
+ return peek(output, length, offset, DEFAULT_MESSAGE);
+ }
+
+/*
+* Peek at a byte in the pipe
+*/
+u32bit Pipe::peek(byte& out, u32bit offset, message_id msg) const
+ {
+ return peek(&out, 1, offset, msg);
+ }
+
+}
diff --git a/botan/src/filters/secqueue.cpp b/botan/src/filters/secqueue.cpp
new file mode 100644
index 0000000..f63ef89
--- /dev/null
+++ b/botan/src/filters/secqueue.cpp
@@ -0,0 +1,205 @@
+/*
+* SecureQueue
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/secqueue.h>
+#include <algorithm>
+
+namespace Botan {
+
+/*
+* SecureQueueNode
+*/
+class SecureQueueNode
+ {
+ public:
+ u32bit write(const byte input[], u32bit length)
+ {
+ u32bit copied = std::min(length, buffer.size() - end);
+ copy_mem(buffer + end, input, copied);
+ end += copied;
+ return copied;
+ }
+ u32bit read(byte output[], u32bit length)
+ {
+ u32bit copied = std::min(length, end - start);
+ copy_mem(output, buffer + start, copied);
+ start += copied;
+ return copied;
+ }
+ u32bit peek(byte output[], u32bit length, u32bit offset = 0)
+ {
+ const u32bit left = end - start;
+ if(offset >= left) return 0;
+ u32bit copied = std::min(length, left - offset);
+ copy_mem(output, buffer + start + offset, copied);
+ return copied;
+ }
+ u32bit size() const { return (end - start); }
+ SecureQueueNode() { next = 0; start = end = 0; }
+ ~SecureQueueNode() { next = 0; start = end = 0; }
+ private:
+ friend class SecureQueue;
+ SecureQueueNode* next;
+ SecureBuffer<byte, DEFAULT_BUFFERSIZE> buffer;
+ u32bit start, end;
+ };
+
+/*
+* Create a SecureQueue
+*/
+SecureQueue::SecureQueue()
+ {
+ set_next(0, 0);
+ head = tail = new SecureQueueNode;
+ }
+
+/*
+* Copy a SecureQueue
+*/
+SecureQueue::SecureQueue(const SecureQueue& input) :
+ Fanout_Filter(), DataSource()
+ {
+ set_next(0, 0);
+
+ head = tail = new SecureQueueNode;
+ SecureQueueNode* temp = input.head;
+ while(temp)
+ {
+ write(temp->buffer + temp->start, temp->end - temp->start);
+ temp = temp->next;
+ }
+ }
+
+/*
+* Destroy this SecureQueue
+*/
+void SecureQueue::destroy()
+ {
+ SecureQueueNode* temp = head;
+ while(temp)
+ {
+ SecureQueueNode* holder = temp->next;
+ delete temp;
+ temp = holder;
+ }
+ head = tail = 0;
+ }
+
+/*
+* Copy a SecureQueue
+*/
+SecureQueue& SecureQueue::operator=(const SecureQueue& input)
+ {
+ destroy();
+ head = tail = new SecureQueueNode;
+ SecureQueueNode* temp = input.head;
+ while(temp)
+ {
+ write(temp->buffer + temp->start, temp->end - temp->start);
+ temp = temp->next;
+ }
+ return (*this);
+ }
+
+/*
+* Add some bytes to the queue
+*/
+void SecureQueue::write(const byte input[], u32bit length)
+ {
+ if(!head)
+ head = tail = new SecureQueueNode;
+ while(length)
+ {
+ const u32bit n = tail->write(input, length);
+ input += n;
+ length -= n;
+ if(length)
+ {
+ tail->next = new SecureQueueNode;
+ tail = tail->next;
+ }
+ }
+ }
+
+/*
+* Read some bytes from the queue
+*/
+u32bit SecureQueue::read(byte output[], u32bit length)
+ {
+ u32bit got = 0;
+ while(length && head)
+ {
+ const u32bit n = head->read(output, length);
+ output += n;
+ got += n;
+ length -= n;
+ if(head->size() == 0)
+ {
+ SecureQueueNode* holder = head->next;
+ delete head;
+ head = holder;
+ }
+ }
+ return got;
+ }
+
+/*
+* Read data, but do not remove it from queue
+*/
+u32bit SecureQueue::peek(byte output[], u32bit length, u32bit offset) const
+ {
+ SecureQueueNode* current = head;
+
+ while(offset && current)
+ {
+ if(offset >= current->size())
+ {
+ offset -= current->size();
+ current = current->next;
+ }
+ else
+ break;
+ }
+
+ u32bit got = 0;
+ while(length && current)
+ {
+ const u32bit n = current->peek(output, length, offset);
+ offset = 0;
+ output += n;
+ got += n;
+ length -= n;
+ current = current->next;
+ }
+ return got;
+ }
+
+/*
+* Return how many bytes the queue holds
+*/
+u32bit SecureQueue::size() const
+ {
+ SecureQueueNode* current = head;
+ u32bit count = 0;
+
+ while(current)
+ {
+ count += current->size();
+ current = current->next;
+ }
+ return count;
+ }
+
+/*
+* Test if the queue has any data in it
+*/
+bool SecureQueue::end_of_data() const
+ {
+ return (size() == 0);
+ }
+
+}
diff --git a/botan/src/filters/secqueue.h b/botan/src/filters/secqueue.h
new file mode 100644
index 0000000..fc1fc21
--- /dev/null
+++ b/botan/src/filters/secqueue.h
@@ -0,0 +1,43 @@
+/*
+* SecureQueue
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SECURE_QUEUE_H__
+#define BOTAN_SECURE_QUEUE_H__
+
+#include <botan/data_src.h>
+#include <botan/filter.h>
+
+namespace Botan {
+
+/*
+* SecureQueue
+*/
+class BOTAN_DLL SecureQueue : public Fanout_Filter, public DataSource
+ {
+ public:
+ void write(const byte[], u32bit);
+
+ u32bit read(byte[], u32bit);
+ u32bit peek(byte[], u32bit, u32bit = 0) const;
+
+ bool end_of_data() const;
+ u32bit size() const;
+ bool attachable() { return false; }
+
+ SecureQueue& operator=(const SecureQueue&);
+ SecureQueue();
+ SecureQueue(const SecureQueue&);
+ ~SecureQueue() { destroy(); }
+ private:
+ void destroy();
+ class SecureQueueNode* head;
+ class SecureQueueNode* tail;
+ };
+
+}
+
+#endif