summaryrefslogtreecommitdiffstats
path: root/botan/src/codec
diff options
context:
space:
mode:
Diffstat (limited to 'botan/src/codec')
-rw-r--r--botan/src/codec/base64/b64_char.cpp47
-rw-r--r--botan/src/codec/base64/base64.cpp228
-rw-r--r--botan/src/codec/base64/base64.h94
-rw-r--r--botan/src/codec/base64/info.txt15
-rw-r--r--botan/src/codec/bzip2/bzip2.cpp275
-rw-r--r--botan/src/codec/bzip2/bzip2.h61
-rw-r--r--botan/src/codec/bzip2/info.txt21
-rw-r--r--botan/src/codec/hex/hex.cpp191
-rw-r--r--botan/src/codec/hex/hex.h90
-rw-r--r--botan/src/codec/hex/hex_char.cpp48
-rw-r--r--botan/src/codec/hex/info.txt15
-rw-r--r--botan/src/codec/openpgp/info.txt15
-rw-r--r--botan/src/codec/openpgp/openpgp.cpp197
-rw-r--r--botan/src/codec/openpgp/openpgp.h34
-rw-r--r--botan/src/codec/pem/info.txt15
-rw-r--r--botan/src/codec/pem/pem.cpp143
-rw-r--r--botan/src/codec/pem/pem.h35
-rw-r--r--botan/src/codec/zlib/info.txt23
-rw-r--r--botan/src/codec/zlib/zlib.cpp287
-rw-r--r--botan/src/codec/zlib/zlib.h58
20 files changed, 1892 insertions, 0 deletions
diff --git a/botan/src/codec/base64/b64_char.cpp b/botan/src/codec/base64/b64_char.cpp
new file mode 100644
index 0000000..e5722a0
--- /dev/null
+++ b/botan/src/codec/base64/b64_char.cpp
@@ -0,0 +1,47 @@
+/*
+* Base64 Codec Character Tables
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/base64.h>
+
+namespace Botan {
+
+/*
+* Base64 Encoder Lookup Table
+*/
+const byte Base64_Encoder::BIN_TO_BASE64[64] = {
+0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D,
+0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A,
+0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D,
+0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A,
+0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x2F };
+
+/*
+* Base64 Decoder Lookup Table
+*/
+const byte Base64_Decoder::BASE64_TO_BIN[256] = {
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x3E, 0x80, 0x80, 0x80, 0x3F, 0x34, 0x35, 0x36, 0x37,
+0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
+0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D,
+0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 };
+
+}
diff --git a/botan/src/codec/base64/base64.cpp b/botan/src/codec/base64/base64.cpp
new file mode 100644
index 0000000..dfcc1ca
--- /dev/null
+++ b/botan/src/codec/base64/base64.cpp
@@ -0,0 +1,228 @@
+/*
+* Base64 Encoder/Decoder
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/base64.h>
+#include <botan/charset.h>
+#include <botan/exceptn.h>
+#include <algorithm>
+
+namespace Botan {
+
+/*
+* Base64_Encoder Constructor
+*/
+Base64_Encoder::Base64_Encoder(bool breaks, u32bit length, bool t_n) :
+ line_length(breaks ? length : 0), trailing_newline(t_n)
+ {
+ in.create(48);
+ out.create(4);
+
+ counter = position = 0;
+ }
+
+/*
+* Base64 Encoding Operation
+*/
+void Base64_Encoder::encode(const byte in[3], byte out[4])
+ {
+ out[0] = BIN_TO_BASE64[((in[0] & 0xFC) >> 2)];
+ out[1] = BIN_TO_BASE64[((in[0] & 0x03) << 4) | (in[1] >> 4)];
+ out[2] = BIN_TO_BASE64[((in[1] & 0x0F) << 2) | (in[2] >> 6)];
+ out[3] = BIN_TO_BASE64[((in[2] & 0x3F) )];
+ }
+
+/*
+* Encode and send a block
+*/
+void Base64_Encoder::encode_and_send(const byte block[], u32bit length)
+ {
+ for(u32bit j = 0; j != length; j += 3)
+ {
+ encode(block + j, out);
+ do_output(out, 4);
+ }
+ }
+
+/*
+* Handle the output
+*/
+void Base64_Encoder::do_output(const byte input[], u32bit length)
+ {
+ if(line_length == 0)
+ send(input, length);
+ else
+ {
+ u32bit remaining = length, offset = 0;
+ while(remaining)
+ {
+ u32bit sent = std::min(line_length - counter, remaining);
+ send(input + offset, sent);
+ counter += sent;
+ remaining -= sent;
+ offset += sent;
+ if(counter == line_length)
+ {
+ send('\n');
+ counter = 0;
+ }
+ }
+ }
+ }
+
+/*
+* Convert some data into Base64
+*/
+void Base64_Encoder::write(const byte input[], u32bit length)
+ {
+ in.copy(position, input, length);
+ if(position + length >= in.size())
+ {
+ encode_and_send(in, in.size());
+ input += (in.size() - position);
+ length -= (in.size() - position);
+ while(length >= in.size())
+ {
+ encode_and_send(input, in.size());
+ input += in.size();
+ length -= in.size();
+ }
+ in.copy(input, length);
+ position = 0;
+ }
+ position += length;
+ }
+
+/*
+* Flush buffers
+*/
+void Base64_Encoder::end_msg()
+ {
+ u32bit start_of_last_block = 3 * (position / 3),
+ left_over = position % 3;
+ encode_and_send(in, start_of_last_block);
+
+ if(left_over)
+ {
+ SecureBuffer<byte, 3> remainder(in + start_of_last_block, left_over);
+
+ encode(remainder, out);
+
+ u32bit empty_bits = 8 * (3 - left_over), index = 4 - 1;
+ while(empty_bits >= 8)
+ {
+ out[index--] = '=';
+ empty_bits -= 6;
+ }
+
+ do_output(out, 4);
+ }
+
+ if(trailing_newline || (counter && line_length))
+ send('\n');
+
+ counter = position = 0;
+ }
+
+/*
+* Base64_Decoder Constructor
+*/
+Base64_Decoder::Base64_Decoder(Decoder_Checking c) : checking(c)
+ {
+ in.create(48);
+ out.create(3);
+ position = 0;
+ }
+
+/*
+* Check if a character is a valid Base64 char
+*/
+bool Base64_Decoder::is_valid(byte in)
+ {
+ return (BASE64_TO_BIN[in] != 0x80);
+ }
+
+/*
+* Base64 Decoding Operation
+*/
+void Base64_Decoder::decode(const byte in[4], byte out[3])
+ {
+ out[0] = ((BASE64_TO_BIN[in[0]] << 2) | (BASE64_TO_BIN[in[1]] >> 4));
+ out[1] = ((BASE64_TO_BIN[in[1]] << 4) | (BASE64_TO_BIN[in[2]] >> 2));
+ out[2] = ((BASE64_TO_BIN[in[2]] << 6) | (BASE64_TO_BIN[in[3]]));
+ }
+
+/*
+* Decode and send a block
+*/
+void Base64_Decoder::decode_and_send(const byte block[], u32bit length)
+ {
+ for(u32bit j = 0; j != length; j += 4)
+ {
+ decode(block + j, out);
+ send(out, 3);
+ }
+ }
+
+/*
+* Handle processing an invalid character
+*/
+void Base64_Decoder::handle_bad_char(byte c)
+ {
+ if(c == '=' || checking == NONE)
+ return;
+
+ if((checking == IGNORE_WS) && Charset::is_space(c))
+ return;
+
+ throw Decoding_Error(
+ std::string("Base64_Decoder: Invalid base64 character '") +
+ static_cast<char>(c) + "'"
+ );
+ }
+
+/*
+* Convert some data from Base64
+*/
+void Base64_Decoder::write(const byte input[], u32bit length)
+ {
+ for(u32bit j = 0; j != length; ++j)
+ {
+ if(is_valid(input[j]))
+ in[position++] = input[j];
+ else
+ handle_bad_char(input[j]);
+
+ if(position == in.size())
+ {
+ decode_and_send(in, in.size());
+ position = 0;
+ }
+ }
+ }
+
+/*
+* Flush buffers
+*/
+void Base64_Decoder::end_msg()
+ {
+ if(position != 0)
+ {
+ u32bit start_of_last_block = 4 * (position / 4),
+ left_over = position % 4;
+ decode_and_send(in, start_of_last_block);
+
+ if(left_over)
+ {
+ SecureBuffer<byte, 4> remainder(in + start_of_last_block, left_over);
+ decode(remainder, out);
+ send(out, ((left_over == 1) ? (1) : (left_over - 1)));
+ }
+ }
+ position = 0;
+ }
+
+}
diff --git a/botan/src/codec/base64/base64.h b/botan/src/codec/base64/base64.h
new file mode 100644
index 0000000..aca02da
--- /dev/null
+++ b/botan/src/codec/base64/base64.h
@@ -0,0 +1,94 @@
+/*
+* Base64 Encoder/Decoder
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_BASE64_H__
+#define BOTAN_BASE64_H__
+
+#include <botan/filter.h>
+
+namespace Botan {
+
+/**
+* This class represents a Base64 encoder.
+*/
+class BOTAN_DLL Base64_Encoder : public Filter
+ {
+ public:
+ static void encode(const byte in[3], byte out[4]);
+
+ /**
+ * Input a part of a message to the encoder.
+ * @param input the message to input as a byte array
+ * @param length the length of the byte array input
+ */
+ void write(const byte input[], u32bit length);
+
+ /**
+ * Inform the Encoder that the current message shall be closed.
+ */
+ void end_msg();
+
+ /**
+ * Create a base64 encoder.
+ * @param breaks whether to use line breaks in the Streamcipheroutput
+ * @param length the length of the lines of the output
+ * @param t_n whether to use a trailing newline
+ */
+ Base64_Encoder(bool breaks = false, u32bit length = 72,
+ bool t_n = false);
+ private:
+ void encode_and_send(const byte[], u32bit);
+ void do_output(const byte[], u32bit);
+ static const byte BIN_TO_BASE64[64];
+
+ const u32bit line_length;
+ const bool trailing_newline;
+ SecureVector<byte> in, out;
+ u32bit position, counter;
+ };
+
+/**
+* This object represents a Base64 decoder.
+*/
+class BOTAN_DLL Base64_Decoder : public Filter
+ {
+ public:
+ static void decode(const byte input[4], byte output[3]);
+
+ static bool is_valid(byte);
+
+ /**
+ * Input a part of a message to the decoder.
+ * @param input the message to input as a byte array
+ * @param length the length of the byte array input
+ */
+ void write(const byte input[], u32bit length);
+
+ /**
+ * Inform the Encoder that the current message shall be closed.
+ */
+ void end_msg();
+
+ /**
+ * Create a base64 encoder.
+ * @param checking the type of checking that shall be performed by
+ * the decoder
+ */
+ Base64_Decoder(Decoder_Checking checking = NONE);
+ private:
+ void decode_and_send(const byte[], u32bit);
+ void handle_bad_char(byte);
+ static const byte BASE64_TO_BIN[256];
+
+ const Decoder_Checking checking;
+ SecureVector<byte> in, out;
+ u32bit position;
+ };
+
+}
+
+#endif
diff --git a/botan/src/codec/base64/info.txt b/botan/src/codec/base64/info.txt
new file mode 100644
index 0000000..d4ed809
--- /dev/null
+++ b/botan/src/codec/base64/info.txt
@@ -0,0 +1,15 @@
+realname "Base64 Codec"
+
+define BASE64_CODEC
+
+load_on auto
+
+<add>
+base64.cpp
+b64_char.cpp
+base64.h
+</add>
+
+<requires>
+filters
+</requires>
diff --git a/botan/src/codec/bzip2/bzip2.cpp b/botan/src/codec/bzip2/bzip2.cpp
new file mode 100644
index 0000000..4cdca53
--- /dev/null
+++ b/botan/src/codec/bzip2/bzip2.cpp
@@ -0,0 +1,275 @@
+/*
+* Bzip Compressor
+* (C) 2001 Peter J Jones
+* 2001-2007 Jack Lloyd
+* 2006 Matt Johnston
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/bzip2.h>
+#include <botan/exceptn.h>
+
+#include <map>
+#include <cstring>
+#define BZ_NO_STDIO
+#include <bzlib.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* Allocation Information for Bzip
+*/
+class Bzip_Alloc_Info
+ {
+ public:
+ std::map<void*, u32bit> current_allocs;
+ Allocator* alloc;
+
+ Bzip_Alloc_Info() { alloc = Allocator::get(false); }
+ };
+
+/*
+* Allocation Function for Bzip
+*/
+void* bzip_malloc(void* info_ptr, int n, int size)
+ {
+ Bzip_Alloc_Info* info = static_cast<Bzip_Alloc_Info*>(info_ptr);
+ void* ptr = info->alloc->allocate(n * size);
+ info->current_allocs[ptr] = n * size;
+ return ptr;
+ }
+
+/*
+* Allocation Function for Bzip
+*/
+void bzip_free(void* info_ptr, void* ptr)
+ {
+ Bzip_Alloc_Info* info = static_cast<Bzip_Alloc_Info*>(info_ptr);
+ std::map<void*, u32bit>::const_iterator i = info->current_allocs.find(ptr);
+ if(i == info->current_allocs.end())
+ throw Invalid_Argument("bzip_free: Got pointer not allocated by us");
+ info->alloc->deallocate(ptr, i->second);
+ }
+
+}
+
+/*
+* Wrapper Type for Bzip2 Stream
+*/
+class Bzip_Stream
+ {
+ public:
+ bz_stream stream;
+
+ Bzip_Stream()
+ {
+ std::memset(&stream, 0, sizeof(bz_stream));
+ stream.bzalloc = bzip_malloc;
+ stream.bzfree = bzip_free;
+ stream.opaque = new Bzip_Alloc_Info;
+ }
+ ~Bzip_Stream()
+ {
+ Bzip_Alloc_Info* info = static_cast<Bzip_Alloc_Info*>(stream.opaque);
+ delete info;
+ std::memset(&stream, 0, sizeof(bz_stream));
+ }
+ };
+
+/*
+* Bzip_Compression Constructor
+*/
+Bzip_Compression::Bzip_Compression(u32bit l) :
+ level((l >= 9) ? 9 : l), buffer(DEFAULT_BUFFERSIZE)
+ {
+ bz = 0;
+ }
+
+/*
+* Start Compressing with Bzip
+*/
+void Bzip_Compression::start_msg()
+ {
+ clear();
+ bz = new Bzip_Stream;
+ if(BZ2_bzCompressInit(&(bz->stream), level, 0, 0) != BZ_OK)
+ throw Exception("Bzip_Compression: Memory allocation error");
+ }
+
+/*
+* Compress Input with Bzip
+*/
+void Bzip_Compression::write(const byte input[], u32bit length)
+ {
+ bz->stream.next_in = reinterpret_cast<char*>(const_cast<byte*>(input));
+ bz->stream.avail_in = length;
+
+ while(bz->stream.avail_in != 0)
+ {
+ bz->stream.next_out = reinterpret_cast<char*>(buffer.begin());
+ bz->stream.avail_out = buffer.size();
+ BZ2_bzCompress(&(bz->stream), BZ_RUN);
+ send(buffer, buffer.size() - bz->stream.avail_out);
+ }
+ }
+
+/*
+* Finish Compressing with Bzip
+*/
+void Bzip_Compression::end_msg()
+ {
+ bz->stream.next_in = 0;
+ bz->stream.avail_in = 0;
+
+ int rc = BZ_OK;
+ while(rc != BZ_STREAM_END)
+ {
+ bz->stream.next_out = reinterpret_cast<char*>(buffer.begin());
+ bz->stream.avail_out = buffer.size();
+ rc = BZ2_bzCompress(&(bz->stream), BZ_FINISH);
+ send(buffer, buffer.size() - bz->stream.avail_out);
+ }
+ clear();
+ }
+
+/*
+* Flush the Bzip Compressor
+*/
+void Bzip_Compression::flush()
+ {
+ bz->stream.next_in = 0;
+ bz->stream.avail_in = 0;
+
+ int rc = BZ_OK;
+ while(rc != BZ_RUN_OK)
+ {
+ bz->stream.next_out = reinterpret_cast<char*>(buffer.begin());
+ bz->stream.avail_out = buffer.size();
+ rc = BZ2_bzCompress(&(bz->stream), BZ_FLUSH);
+ send(buffer, buffer.size() - bz->stream.avail_out);
+ }
+ }
+
+/*
+* Clean up Compression Context
+*/
+void Bzip_Compression::clear()
+ {
+ if(!bz) return;
+ BZ2_bzCompressEnd(&(bz->stream));
+ delete bz;
+ bz = 0;
+ }
+
+/*
+* Bzip_Decompression Constructor
+*/
+Bzip_Decompression::Bzip_Decompression(bool s) :
+ small_mem(s), buffer(DEFAULT_BUFFERSIZE)
+ {
+ no_writes = true;
+ bz = 0;
+ }
+
+/*
+* Decompress Input with Bzip
+*/
+void Bzip_Decompression::write(const byte input_arr[], u32bit length)
+ {
+ if(length) no_writes = false;
+
+ char* input = reinterpret_cast<char*>(const_cast<byte*>(input_arr));
+
+ bz->stream.next_in = input;
+ bz->stream.avail_in = length;
+
+ while(bz->stream.avail_in != 0)
+ {
+ bz->stream.next_out = reinterpret_cast<char*>(buffer.begin());
+ bz->stream.avail_out = buffer.size();
+
+ int rc = BZ2_bzDecompress(&(bz->stream));
+
+ if(rc != BZ_OK && rc != BZ_STREAM_END)
+ {
+ clear();
+ if(rc == BZ_DATA_ERROR)
+ throw Decoding_Error("Bzip_Decompression: Data integrity error");
+ if(rc == BZ_DATA_ERROR_MAGIC)
+ throw Decoding_Error("Bzip_Decompression: Invalid input");
+ if(rc == BZ_MEM_ERROR)
+ throw Exception("Bzip_Decompression: Memory allocation error");
+ throw Exception("Bzip_Decompression: Unknown decompress error");
+ }
+
+ send(buffer, buffer.size() - bz->stream.avail_out);
+
+ if(rc == BZ_STREAM_END)
+ {
+ u32bit read_from_block = length - bz->stream.avail_in;
+ start_msg();
+ bz->stream.next_in = input + read_from_block;
+ bz->stream.avail_in = length - read_from_block;
+ input += read_from_block;
+ length -= read_from_block;
+ }
+ }
+ }
+
+/*
+* Start Decompressing with Bzip
+*/
+void Bzip_Decompression::start_msg()
+ {
+ clear();
+ bz = new Bzip_Stream;
+
+ if(BZ2_bzDecompressInit(&(bz->stream), 0, small_mem) != BZ_OK)
+ throw Exception("Bzip_Decompression: Memory allocation error");
+
+ no_writes = true;
+ }
+
+/*
+* Finish Decompressing with Bzip
+*/
+void Bzip_Decompression::end_msg()
+ {
+ if(no_writes) return;
+ bz->stream.next_in = 0;
+ bz->stream.avail_in = 0;
+
+ int rc = BZ_OK;
+ while(rc != BZ_STREAM_END)
+ {
+ bz->stream.next_out = reinterpret_cast<char*>(buffer.begin());
+ bz->stream.avail_out = buffer.size();
+ rc = BZ2_bzDecompress(&(bz->stream));
+
+ if(rc != BZ_OK && rc != BZ_STREAM_END)
+ {
+ clear();
+ throw Exception("Bzip_Decompression: Error finalizing decompression");
+ }
+
+ send(buffer, buffer.size() - bz->stream.avail_out);
+ }
+
+ clear();
+ }
+
+/*
+* Clean up Decompression Context
+*/
+void Bzip_Decompression::clear()
+ {
+ if(!bz) return;
+ BZ2_bzDecompressEnd(&(bz->stream));
+ delete bz;
+ bz = 0;
+ }
+
+}
diff --git a/botan/src/codec/bzip2/bzip2.h b/botan/src/codec/bzip2/bzip2.h
new file mode 100644
index 0000000..f422635
--- /dev/null
+++ b/botan/src/codec/bzip2/bzip2.h
@@ -0,0 +1,61 @@
+/*
+* Bzip Compressor
+* (C) 2001 Peter J Jones
+* 2001-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_BZIP2_H__
+#define BOTAN_BZIP2_H__
+
+#include <botan/filter.h>
+
+namespace Botan {
+
+/*
+* Bzip Compression Filter
+*/
+class BOTAN_DLL Bzip_Compression : public Filter
+ {
+ public:
+ void write(const byte input[], u32bit length);
+ void start_msg();
+ void end_msg();
+
+ void flush();
+
+ Bzip_Compression(u32bit = 9);
+ ~Bzip_Compression() { clear(); }
+ private:
+ void clear();
+
+ const u32bit level;
+ SecureVector<byte> buffer;
+ class Bzip_Stream* bz;
+ };
+
+/*
+* Bzip Decompression Filter
+*/
+class BOTAN_DLL Bzip_Decompression : public Filter
+ {
+ public:
+ void write(const byte input[], u32bit length);
+ void start_msg();
+ void end_msg();
+
+ Bzip_Decompression(bool = false);
+ ~Bzip_Decompression() { clear(); }
+ private:
+ void clear();
+
+ const bool small_mem;
+ SecureVector<byte> buffer;
+ class Bzip_Stream* bz;
+ bool no_writes;
+ };
+
+}
+
+#endif
diff --git a/botan/src/codec/bzip2/info.txt b/botan/src/codec/bzip2/info.txt
new file mode 100644
index 0000000..1be84e4
--- /dev/null
+++ b/botan/src/codec/bzip2/info.txt
@@ -0,0 +1,21 @@
+# This module was written by Peter J. Jones
+
+realname "Bzip2 Compressor"
+
+define COMPRESSOR_BZIP2
+modset compression
+
+load_on request
+
+<add>
+bzip2.h
+bzip2.cpp
+</add>
+
+<libs>
+all -> bz2
+</libs>
+
+<requires>
+filters
+</requires>
diff --git a/botan/src/codec/hex/hex.cpp b/botan/src/codec/hex/hex.cpp
new file mode 100644
index 0000000..fbacc27
--- /dev/null
+++ b/botan/src/codec/hex/hex.cpp
@@ -0,0 +1,191 @@
+/*
+* Hex Encoder/Decoder
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/hex.h>
+#include <botan/parsing.h>
+#include <botan/charset.h>
+#include <botan/exceptn.h>
+#include <algorithm>
+
+namespace Botan {
+
+/*
+* Hex_Encoder Constructor
+*/
+Hex_Encoder::Hex_Encoder(bool breaks, u32bit length, Case c) :
+ casing(c), line_length(breaks ? length : 0)
+ {
+ in.create(64);
+ out.create(2*in.size());
+ counter = position = 0;
+ }
+
+/*
+* Hex_Encoder Constructor
+*/
+Hex_Encoder::Hex_Encoder(Case c) : casing(c), line_length(0)
+ {
+ in.create(64);
+ out.create(2*in.size());
+ counter = position = 0;
+ }
+
+/*
+* Hex Encoding Operation
+*/
+void Hex_Encoder::encode(byte in, byte out[2], Hex_Encoder::Case casing)
+ {
+ const byte* BIN_TO_HEX = ((casing == Uppercase) ? BIN_TO_HEX_UPPER :
+ BIN_TO_HEX_LOWER);
+
+ out[0] = BIN_TO_HEX[((in >> 4) & 0x0F)];
+ out[1] = BIN_TO_HEX[((in ) & 0x0F)];
+ }
+
+/*
+* Encode and send a block
+*/
+void Hex_Encoder::encode_and_send(const byte block[], u32bit length)
+ {
+ for(u32bit j = 0; j != length; ++j)
+ encode(block[j], out + 2*j, casing);
+
+ if(line_length == 0)
+ send(out, 2*length);
+ else
+ {
+ u32bit remaining = 2*length, offset = 0;
+ while(remaining)
+ {
+ u32bit sent = std::min(line_length - counter, remaining);
+ send(out + offset, sent);
+ counter += sent;
+ remaining -= sent;
+ offset += sent;
+ if(counter == line_length)
+ {
+ send('\n');
+ counter = 0;
+ }
+ }
+ }
+ }
+
+/*
+* Convert some data into hex format
+*/
+void Hex_Encoder::write(const byte input[], u32bit length)
+ {
+ in.copy(position, input, length);
+ if(position + length >= in.size())
+ {
+ encode_and_send(in, in.size());
+ input += (in.size() - position);
+ length -= (in.size() - position);
+ while(length >= in.size())
+ {
+ encode_and_send(input, in.size());
+ input += in.size();
+ length -= in.size();
+ }
+ in.copy(input, length);
+ position = 0;
+ }
+ position += length;
+ }
+
+/*
+* Flush buffers
+*/
+void Hex_Encoder::end_msg()
+ {
+ encode_and_send(in, position);
+ if(counter && line_length)
+ send('\n');
+ counter = position = 0;
+ }
+
+/*
+* Hex_Decoder Constructor
+*/
+Hex_Decoder::Hex_Decoder(Decoder_Checking c) : checking(c)
+ {
+ in.create(64);
+ out.create(in.size() / 2);
+ position = 0;
+ }
+
+/*
+* Check if a character is a valid hex char
+*/
+bool Hex_Decoder::is_valid(byte in)
+ {
+ return (HEX_TO_BIN[in] != 0x80);
+ }
+
+/*
+* Handle processing an invalid character
+*/
+void Hex_Decoder::handle_bad_char(byte c)
+ {
+ if(checking == NONE)
+ return;
+
+ if((checking == IGNORE_WS) && Charset::is_space(c))
+ return;
+
+ throw Decoding_Error("Hex_Decoder: Invalid hex character: " +
+ to_string(c));
+ }
+
+/*
+* Hex Decoding Operation
+*/
+byte Hex_Decoder::decode(const byte hex[2])
+ {
+ return ((HEX_TO_BIN[hex[0]] << 4) | HEX_TO_BIN[hex[1]]);
+ }
+
+/*
+* Decode and send a block
+*/
+void Hex_Decoder::decode_and_send(const byte block[], u32bit length)
+ {
+ for(u32bit j = 0; j != length / 2; ++j)
+ out[j] = decode(block + 2*j);
+ send(out, length / 2);
+ }
+
+/*
+* Convert some data from hex format
+*/
+void Hex_Decoder::write(const byte input[], u32bit length)
+ {
+ for(u32bit j = 0; j != length; ++j)
+ {
+ if(is_valid(input[j]))
+ in[position++] = input[j];
+ else
+ handle_bad_char(input[j]);
+ if(position == in.size())
+ {
+ decode_and_send(in, in.size());
+ position = 0;
+ }
+ }
+ }
+
+/*
+* Flush buffers
+*/
+void Hex_Decoder::end_msg()
+ {
+ decode_and_send(in, position);
+ position = 0;
+ }
+
+}
diff --git a/botan/src/codec/hex/hex.h b/botan/src/codec/hex/hex.h
new file mode 100644
index 0000000..035bf4e
--- /dev/null
+++ b/botan/src/codec/hex/hex.h
@@ -0,0 +1,90 @@
+/*
+* Hex Encoder/Decoder
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_HEX_H__
+#define BOTAN_HEX_H__
+
+#include <botan/filter.h>
+
+namespace Botan {
+
+/**
+* This class represents a hex encoder. It encodes byte arrays to hex strings.
+*/
+class BOTAN_DLL Hex_Encoder : public Filter
+ {
+ public:
+ /**
+ * Whether to use uppercase or lowercase letters for the encoded string.
+ */
+ enum Case { Uppercase, Lowercase };
+
+ /**
+ Encode a single byte into two hex characters
+ */
+ static void encode(byte in, byte out[2], Case the_case = Uppercase);
+
+ void write(const byte in[], u32bit length);
+ void end_msg();
+
+ /**
+ * Create a hex encoder.
+ * @param the_case the case to use in the encoded strings.
+ */
+ Hex_Encoder(Case the_case);
+
+ /**
+ * Create a hex encoder.
+ * @param newlines should newlines be used
+ * @param line_length if newlines are used, how long are lines
+ * @param the_case the case to use in the encoded strings
+ */
+ Hex_Encoder(bool newlines = false,
+ u32bit line_length = 72,
+ Case the_case = Uppercase);
+ private:
+ void encode_and_send(const byte[], u32bit);
+ static const byte BIN_TO_HEX_UPPER[16];
+ static const byte BIN_TO_HEX_LOWER[16];
+
+ const Case casing;
+ const u32bit line_length;
+ SecureVector<byte> in, out;
+ u32bit position, counter;
+ };
+
+/**
+* This class represents a hex decoder. It converts hex strings to byte arrays.
+*/
+class BOTAN_DLL Hex_Decoder : public Filter
+ {
+ public:
+ static byte decode(const byte[2]);
+ static bool is_valid(byte);
+
+ void write(const byte[], u32bit);
+ void end_msg();
+
+ /**
+ * Construct a Hex Decoder using the specified
+ * character checking.
+ * @param checking the checking to use during decoding.
+ */
+ Hex_Decoder(Decoder_Checking checking = NONE);
+ private:
+ void decode_and_send(const byte[], u32bit);
+ void handle_bad_char(byte);
+ static const byte HEX_TO_BIN[256];
+
+ const Decoder_Checking checking;
+ SecureVector<byte> in, out;
+ u32bit position;
+ };
+
+}
+
+#endif
diff --git a/botan/src/codec/hex/hex_char.cpp b/botan/src/codec/hex/hex_char.cpp
new file mode 100644
index 0000000..c28efc5
--- /dev/null
+++ b/botan/src/codec/hex/hex_char.cpp
@@ -0,0 +1,48 @@
+/*
+* Hex Character Table
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/hex.h>
+
+namespace Botan {
+
+/*
+* Hex Encoder Lookup Tables
+*/
+const byte Hex_Encoder::BIN_TO_HEX_UPPER[16] = {
+0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43,
+0x44, 0x45, 0x46 };
+
+const byte Hex_Encoder::BIN_TO_HEX_LOWER[16] = {
+0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63,
+0x64, 0x65, 0x66 };
+
+/*
+* Hex Decoder Lookup Table
+*/
+const byte Hex_Decoder::HEX_TO_BIN[256] = {
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x01, 0x02, 0x03,
+0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 };
+
+}
diff --git a/botan/src/codec/hex/info.txt b/botan/src/codec/hex/info.txt
new file mode 100644
index 0000000..512a5de
--- /dev/null
+++ b/botan/src/codec/hex/info.txt
@@ -0,0 +1,15 @@
+realname "Hex Codec"
+
+define HEX_CODEC
+
+load_on auto
+
+<add>
+hex.cpp
+hex_char.cpp
+hex.h
+</add>
+
+<requires>
+filters
+</requires>
diff --git a/botan/src/codec/openpgp/info.txt b/botan/src/codec/openpgp/info.txt
new file mode 100644
index 0000000..6b30850
--- /dev/null
+++ b/botan/src/codec/openpgp/info.txt
@@ -0,0 +1,15 @@
+realname "OpenPGP Codec"
+
+define OPENPGP_CODEC
+
+load_on auto
+
+<add>
+openpgp.cpp
+openpgp.h
+</add>
+
+<requires>
+crc24
+filters
+</requires>
diff --git a/botan/src/codec/openpgp/openpgp.cpp b/botan/src/codec/openpgp/openpgp.cpp
new file mode 100644
index 0000000..7f9cf5f
--- /dev/null
+++ b/botan/src/codec/openpgp/openpgp.cpp
@@ -0,0 +1,197 @@
+/*
+* OpenPGP
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/openpgp.h>
+#include <botan/filters.h>
+#include <botan/charset.h>
+#include <botan/crc24.h>
+
+namespace Botan {
+
+namespace OpenPGP {
+
+/*
+* OpenPGP Base64 encoding
+*/
+std::string encode(const byte input[], u32bit length,
+ const std::string& label,
+ const std::map<std::string, std::string>& headers)
+ {
+ const std::string PGP_HEADER = "-----BEGIN PGP " + label + "-----\n";
+ const std::string PGP_TRAILER = "-----END PGP " + label + "-----\n";
+ const u32bit PGP_WIDTH = 64;
+
+ std::string pgp_encoded = PGP_HEADER;
+
+ if(headers.find("Version") != headers.end())
+ pgp_encoded += "Version: " + headers.find("Version")->second + '\n';
+
+ std::map<std::string, std::string>::const_iterator i = headers.begin();
+ while(i != headers.end())
+ {
+ if(i->first != "Version")
+ pgp_encoded += i->first + ": " + i->second + '\n';
+ ++i;
+ }
+ pgp_encoded += '\n';
+
+ Pipe pipe(new Fork(
+ new Base64_Encoder(true, PGP_WIDTH),
+ new Chain(new Hash_Filter(new CRC24), new Base64_Encoder)
+ )
+ );
+
+ pipe.process_msg(input, length);
+
+ pgp_encoded += pipe.read_all_as_string(0);
+ pgp_encoded += '=' + pipe.read_all_as_string(1) + '\n';
+ pgp_encoded += PGP_TRAILER;
+
+ return pgp_encoded;
+ }
+
+/*
+* OpenPGP Base64 encoding
+*/
+std::string encode(const byte input[], u32bit length,
+ const std::string& type)
+ {
+ std::map<std::string, std::string> empty;
+ return encode(input, length, type, empty);
+ }
+
+/*
+* OpenPGP Base64 decoding
+*/
+SecureVector<byte> decode(DataSource& source, std::string& label,
+ std::map<std::string, std::string>& headers)
+ {
+ const u32bit RANDOM_CHAR_LIMIT = 5;
+
+ const std::string PGP_HEADER1 = "-----BEGIN PGP ";
+ const std::string PGP_HEADER2 = "-----";
+ u32bit position = 0;
+
+ while(position != PGP_HEADER1.length())
+ {
+ byte b;
+ if(!source.read_byte(b))
+ throw Decoding_Error("PGP: No PGP header found");
+ if(b == PGP_HEADER1[position])
+ ++position;
+ else if(position >= RANDOM_CHAR_LIMIT)
+ throw Decoding_Error("PGP: Malformed PGP header");
+ else
+ position = 0;
+ }
+ position = 0;
+ while(position != PGP_HEADER2.length())
+ {
+ byte b;
+ if(!source.read_byte(b))
+ throw Decoding_Error("PGP: No PGP header found");
+ if(b == PGP_HEADER2[position])
+ ++position;
+ else if(position)
+ throw Decoding_Error("PGP: Malformed PGP header");
+
+ if(position == 0)
+ label += static_cast<char>(b);
+ }
+
+ headers.clear();
+ bool end_of_headers = false;
+ while(!end_of_headers)
+ {
+ std::string this_header;
+ byte b = 0;
+ while(b != '\n')
+ {
+ if(!source.read_byte(b))
+ throw Decoding_Error("PGP: Bad armor header");
+ if(b != '\n')
+ this_header += static_cast<char>(b);
+ }
+
+ end_of_headers = true;
+ for(u32bit j = 0; j != this_header.length(); ++j)
+ if(!Charset::is_space(this_header[j]))
+ end_of_headers = false;
+
+ if(!end_of_headers)
+ {
+ std::string::size_type pos = this_header.find(": ");
+ if(pos == std::string::npos)
+ throw Decoding_Error("OpenPGP: Bad headers");
+
+ std::string key = this_header.substr(0, pos);
+ std::string value = this_header.substr(pos + 2, std::string::npos);
+ headers[key] = value;
+ }
+ }
+
+ Pipe base64(new Base64_Decoder,
+ new Fork(0,
+ new Chain(new Hash_Filter(new CRC24),
+ new Base64_Encoder)
+ )
+ );
+ base64.start_msg();
+
+ const std::string PGP_TRAILER = "-----END PGP " + label + "-----";
+ position = 0;
+ bool newline_seen = 0;
+ std::string crc;
+ while(position != PGP_TRAILER.length())
+ {
+ byte b;
+ if(!source.read_byte(b))
+ throw Decoding_Error("PGP: No PGP trailer found");
+ if(b == PGP_TRAILER[position])
+ ++position;
+ else if(position)
+ throw Decoding_Error("PGP: Malformed PGP trailer");
+
+ if(b == '=' && newline_seen)
+ {
+ while(b != '\n')
+ {
+ if(!source.read_byte(b))
+ throw Decoding_Error("PGP: Bad CRC tail");
+ if(b != '\n')
+ crc += static_cast<char>(b);
+ }
+ }
+ else if(b == '\n')
+ newline_seen = true;
+ else if(position == 0)
+ {
+ base64.write(b);
+ newline_seen = false;
+ }
+ }
+ base64.end_msg();
+
+ if(crc != "" && crc != base64.read_all_as_string(1))
+ throw Decoding_Error("PGP: Corrupt CRC");
+
+ return base64.read_all();
+ }
+
+/*
+* OpenPGP Base64 decoding
+*/
+SecureVector<byte> decode(DataSource& source, std::string& label)
+ {
+ std::map<std::string, std::string> ignored;
+ return decode(source, label, ignored);
+ }
+
+}
+
+}
+
diff --git a/botan/src/codec/openpgp/openpgp.h b/botan/src/codec/openpgp/openpgp.h
new file mode 100644
index 0000000..890fcf0
--- /dev/null
+++ b/botan/src/codec/openpgp/openpgp.h
@@ -0,0 +1,34 @@
+/*
+* OpenPGP
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_OPENPGP_H__
+#define BOTAN_OPENPGP_H__
+
+#include <botan/data_src.h>
+#include <string>
+#include <map>
+
+namespace Botan {
+
+namespace OpenPGP {
+
+/*
+* OpenPGP Base64 encoding/decoding
+*/
+BOTAN_DLL std::string encode(const byte[], u32bit, const std::string&,
+ const std::map<std::string, std::string>&);
+BOTAN_DLL SecureVector<byte> decode(DataSource&, std::string&,
+ std::map<std::string, std::string>&);
+
+BOTAN_DLL std::string encode(const byte[], u32bit, const std::string&);
+BOTAN_DLL SecureVector<byte> decode(DataSource&, std::string&);
+
+}
+
+}
+
+#endif
diff --git a/botan/src/codec/pem/info.txt b/botan/src/codec/pem/info.txt
new file mode 100644
index 0000000..bbe8d4c
--- /dev/null
+++ b/botan/src/codec/pem/info.txt
@@ -0,0 +1,15 @@
+realname "PEM Codec"
+
+define PEM_CODEC
+
+load_on auto
+
+<add>
+pem.cpp
+pem.h
+</add>
+
+<requires>
+base64
+filters
+</requires>
diff --git a/botan/src/codec/pem/pem.cpp b/botan/src/codec/pem/pem.cpp
new file mode 100644
index 0000000..5141bee
--- /dev/null
+++ b/botan/src/codec/pem/pem.cpp
@@ -0,0 +1,143 @@
+/*
+* PEM Encoding/Decoding
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/pem.h>
+#include <botan/filters.h>
+#include <botan/parsing.h>
+
+namespace Botan {
+
+namespace PEM_Code {
+
+/*
+* PEM encode BER/DER-encoded objects
+*/
+std::string encode(const byte der[], u32bit length, const std::string& label,
+ u32bit width)
+ {
+ const std::string PEM_HEADER = "-----BEGIN " + label + "-----\n";
+ const std::string PEM_TRAILER = "-----END " + label + "-----\n";
+
+ Pipe pipe(new Base64_Encoder(true, width));
+ pipe.process_msg(der, length);
+ return (PEM_HEADER + pipe.read_all_as_string() + PEM_TRAILER);
+ }
+
+/*
+* PEM encode BER/DER-encoded objects
+*/
+std::string encode(const MemoryRegion<byte>& data, const std::string& label,
+ u32bit width)
+ {
+ return encode(data, data.size(), label, width);
+ }
+
+/*
+* Decode PEM down to raw BER/DER
+*/
+SecureVector<byte> decode_check_label(DataSource& source,
+ const std::string& label_want)
+ {
+ std::string label_got;
+ SecureVector<byte> ber = decode(source, label_got);
+ if(label_got != label_want)
+ throw Decoding_Error("PEM: Label mismatch, wanted " + label_want +
+ ", got " + label_got);
+ return ber;
+ }
+
+/*
+* Decode PEM down to raw BER/DER
+*/
+SecureVector<byte> decode(DataSource& source, std::string& label)
+ {
+ const u32bit RANDOM_CHAR_LIMIT = 8;
+
+ const std::string PEM_HEADER1 = "-----BEGIN ";
+ const std::string PEM_HEADER2 = "-----";
+ u32bit position = 0;
+
+ while(position != PEM_HEADER1.length())
+ {
+ byte b;
+ if(!source.read_byte(b))
+ throw Decoding_Error("PEM: No PEM header found");
+ if(b == PEM_HEADER1[position])
+ ++position;
+ else if(position >= RANDOM_CHAR_LIMIT)
+ throw Decoding_Error("PEM: Malformed PEM header");
+ else
+ position = 0;
+ }
+ position = 0;
+ while(position != PEM_HEADER2.length())
+ {
+ byte b;
+ if(!source.read_byte(b))
+ throw Decoding_Error("PEM: No PEM header found");
+ if(b == PEM_HEADER2[position])
+ ++position;
+ else if(position)
+ throw Decoding_Error("PEM: Malformed PEM header");
+
+ if(position == 0)
+ label += static_cast<char>(b);
+ }
+
+ Pipe base64(new Base64_Decoder);
+ base64.start_msg();
+
+ const std::string PEM_TRAILER = "-----END " + label + "-----";
+ position = 0;
+ while(position != PEM_TRAILER.length())
+ {
+ byte b;
+ if(!source.read_byte(b))
+ throw Decoding_Error("PEM: No PEM trailer found");
+ if(b == PEM_TRAILER[position])
+ ++position;
+ else if(position)
+ throw Decoding_Error("PEM: Malformed PEM trailer");
+
+ if(position == 0)
+ base64.write(b);
+ }
+ base64.end_msg();
+ return base64.read_all();
+ }
+
+/*
+* Search for a PEM signature
+*/
+bool matches(DataSource& source, const std::string& extra,
+ u32bit search_range)
+ {
+ const std::string PEM_HEADER = "-----BEGIN " + extra;
+
+ SecureVector<byte> search_buf(search_range);
+ u32bit got = source.peek(search_buf, search_buf.size(), 0);
+
+ if(got < PEM_HEADER.length())
+ return false;
+
+ u32bit index = 0;
+
+ for(u32bit j = 0; j != got; ++j)
+ {
+ if(search_buf[j] == PEM_HEADER[index])
+ ++index;
+ else
+ index = 0;
+ if(index == PEM_HEADER.size())
+ return true;
+ }
+ return false;
+ }
+
+}
+
+}
diff --git a/botan/src/codec/pem/pem.h b/botan/src/codec/pem/pem.h
new file mode 100644
index 0000000..9fe8acb
--- /dev/null
+++ b/botan/src/codec/pem/pem.h
@@ -0,0 +1,35 @@
+/*
+* PEM Encoding/Decoding
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PEM_H__
+#define BOTAN_PEM_H__
+
+#include <botan/data_src.h>
+
+namespace Botan {
+
+namespace PEM_Code {
+
+/*
+* PEM Encoding/Decoding
+*/
+BOTAN_DLL std::string encode(const byte[], u32bit,
+ const std::string&, u32bit = 64);
+BOTAN_DLL std::string encode(const MemoryRegion<byte>&,
+ const std::string&, u32bit = 64);
+
+BOTAN_DLL SecureVector<byte> decode(DataSource&, std::string&);
+BOTAN_DLL SecureVector<byte> decode_check_label(DataSource&,
+ const std::string&);
+BOTAN_DLL bool matches(DataSource&, const std::string& = "",
+ u32bit search_range = 4096);
+
+}
+
+}
+
+#endif
diff --git a/botan/src/codec/zlib/info.txt b/botan/src/codec/zlib/info.txt
new file mode 100644
index 0000000..9b1c35d
--- /dev/null
+++ b/botan/src/codec/zlib/info.txt
@@ -0,0 +1,23 @@
+realname "Zlib Compressor"
+#realname "Zlib/Gzip Compressor"
+
+define COMPRESSOR_ZLIB
+#define COMPRESSOR_ZLIB,COMPRESSOR_GZIP
+
+load_on request
+modset compression
+
+<add>
+zlib.h
+zlib.cpp
+#gzip.h
+#gzip.cpp
+</add>
+
+<libs>
+all -> z
+</libs>
+
+<requires>
+filters
+</requires>
diff --git a/botan/src/codec/zlib/zlib.cpp b/botan/src/codec/zlib/zlib.cpp
new file mode 100644
index 0000000..246e329
--- /dev/null
+++ b/botan/src/codec/zlib/zlib.cpp
@@ -0,0 +1,287 @@
+/*
+* Zlib Compressor
+* (C) 2001 Peter J Jones
+* 2001-2007 Jack Lloyd
+* 2006 Matt Johnston
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/zlib.h>
+#include <botan/exceptn.h>
+
+#include <cstring>
+#include <map>
+#include <zlib.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* Allocation Information for Zlib
+*/
+class Zlib_Alloc_Info
+ {
+ public:
+ std::map<void*, u32bit> current_allocs;
+ Allocator* alloc;
+
+ Zlib_Alloc_Info() { alloc = Allocator::get(false); }
+ };
+
+/*
+* Allocation Function for Zlib
+*/
+void* zlib_malloc(void* info_ptr, unsigned int n, unsigned int size)
+ {
+ Zlib_Alloc_Info* info = static_cast<Zlib_Alloc_Info*>(info_ptr);
+ void* ptr = info->alloc->allocate(n * size);
+ info->current_allocs[ptr] = n * size;
+ return ptr;
+ }
+
+/*
+* Allocation Function for Zlib
+*/
+void zlib_free(void* info_ptr, void* ptr)
+ {
+ Zlib_Alloc_Info* info = static_cast<Zlib_Alloc_Info*>(info_ptr);
+ std::map<void*, u32bit>::const_iterator i = info->current_allocs.find(ptr);
+ if(i == info->current_allocs.end())
+ throw Invalid_Argument("zlib_free: Got pointer not allocated by us");
+ info->alloc->deallocate(ptr, i->second);
+ }
+
+}
+
+/*
+* Wrapper Type for Zlib z_stream
+*/
+class Zlib_Stream
+ {
+ public:
+ z_stream stream;
+
+ Zlib_Stream()
+ {
+ std::memset(&stream, 0, sizeof(z_stream));
+ stream.zalloc = zlib_malloc;
+ stream.zfree = zlib_free;
+ stream.opaque = new Zlib_Alloc_Info;
+ }
+ ~Zlib_Stream()
+ {
+ Zlib_Alloc_Info* info = static_cast<Zlib_Alloc_Info*>(stream.opaque);
+ delete info;
+ std::memset(&stream, 0, sizeof(z_stream));
+ }
+ };
+
+/*
+* Zlib_Compression Constructor
+*/
+Zlib_Compression::Zlib_Compression(u32bit l) :
+ level((l >= 9) ? 9 : l), buffer(DEFAULT_BUFFERSIZE)
+ {
+ zlib = 0;
+ }
+
+/*
+* Start Compressing with Zlib
+*/
+void Zlib_Compression::start_msg()
+ {
+ clear();
+ zlib = new Zlib_Stream;
+ if(deflateInit(&(zlib->stream), level) != Z_OK)
+ throw Exception("Zlib_Compression: Memory allocation error");
+ }
+
+/*
+* Compress Input with Zlib
+*/
+void Zlib_Compression::write(const byte input[], u32bit length)
+ {
+ zlib->stream.next_in = static_cast<Bytef*>(const_cast<byte*>(input));
+ zlib->stream.avail_in = length;
+
+ while(zlib->stream.avail_in != 0)
+ {
+ zlib->stream.next_out = static_cast<Bytef*>(buffer.begin());
+ zlib->stream.avail_out = buffer.size();
+ deflate(&(zlib->stream), Z_NO_FLUSH);
+ send(buffer.begin(), buffer.size() - zlib->stream.avail_out);
+ }
+ }
+
+/*
+* Finish Compressing with Zlib
+*/
+void Zlib_Compression::end_msg()
+ {
+ zlib->stream.next_in = 0;
+ zlib->stream.avail_in = 0;
+
+ int rc = Z_OK;
+ while(rc != Z_STREAM_END)
+ {
+ zlib->stream.next_out = reinterpret_cast<Bytef*>(buffer.begin());
+ zlib->stream.avail_out = buffer.size();
+ rc = deflate(&(zlib->stream), Z_FINISH);
+ send(buffer.begin(), buffer.size() - zlib->stream.avail_out);
+ }
+ clear();
+ }
+
+/*
+* Flush the Zlib Compressor
+*/
+void Zlib_Compression::flush()
+ {
+ zlib->stream.next_in = 0;
+ zlib->stream.avail_in = 0;
+
+ while(true)
+ {
+ zlib->stream.avail_out = buffer.size();
+
+ zlib->stream.next_out = reinterpret_cast<Bytef*>(buffer.begin());
+
+
+ deflate(&(zlib->stream), Z_FULL_FLUSH);
+ send(buffer.begin(), buffer.size() - zlib->stream.avail_out);
+ if(zlib->stream.avail_out == buffer.size()) break;
+ }
+ }
+
+/*
+* Clean up Compression Context
+*/
+void Zlib_Compression::clear()
+ {
+ if(zlib)
+ {
+ deflateEnd(&(zlib->stream));
+ delete zlib;
+ zlib = 0;
+ }
+
+ buffer.clear();
+ }
+
+/*
+* Zlib_Decompression Constructor
+*/
+Zlib_Decompression::Zlib_Decompression() : buffer(DEFAULT_BUFFERSIZE)
+ {
+ zlib = 0;
+ no_writes = true;
+ }
+
+/*
+* Start Decompressing with Zlib
+*/
+void Zlib_Decompression::start_msg()
+ {
+ clear();
+ zlib = new Zlib_Stream;
+ if(inflateInit(&(zlib->stream)) != Z_OK)
+ throw Exception("Zlib_Decompression: Memory allocation error");
+ }
+
+/*
+* Decompress Input with Zlib
+*/
+void Zlib_Decompression::write(const byte input_arr[], u32bit length)
+ {
+ if(length) no_writes = false;
+
+ // non-const needed by zlib api :(
+ Bytef* input = reinterpret_cast<Bytef*>(const_cast<byte*>(input_arr));
+
+ zlib->stream.next_in = input;
+ zlib->stream.avail_in = length;
+
+ while(zlib->stream.avail_in != 0)
+ {
+ zlib->stream.next_out = reinterpret_cast<Bytef*>(buffer.begin());
+ zlib->stream.avail_out = buffer.size();
+
+ int rc = inflate(&(zlib->stream), Z_SYNC_FLUSH);
+
+ if(rc != Z_OK && rc != Z_STREAM_END)
+ {
+ clear();
+ if(rc == Z_DATA_ERROR)
+ throw Decoding_Error("Zlib_Decompression: Data integrity error");
+ if(rc == Z_NEED_DICT)
+ throw Decoding_Error("Zlib_Decompression: Need preset dictionary");
+ if(rc == Z_MEM_ERROR)
+ throw Exception("Zlib_Decompression: Memory allocation error");
+ throw Exception("Zlib_Decompression: Unknown decompress error");
+ }
+
+ send(buffer.begin(), buffer.size() - zlib->stream.avail_out);
+
+ if(rc == Z_STREAM_END)
+ {
+ u32bit read_from_block = length - zlib->stream.avail_in;
+ start_msg();
+
+ zlib->stream.next_in = input + read_from_block;
+ zlib->stream.avail_in = length - read_from_block;
+
+ input += read_from_block;
+ length -= read_from_block;
+ }
+ }
+ }
+
+/*
+* Finish Decompressing with Zlib
+*/
+void Zlib_Decompression::end_msg()
+ {
+ if(no_writes) return;
+ zlib->stream.next_in = 0;
+ zlib->stream.avail_in = 0;
+
+ int rc = Z_OK;
+
+ while(rc != Z_STREAM_END)
+ {
+ zlib->stream.next_out = reinterpret_cast<Bytef*>(buffer.begin());
+ zlib->stream.avail_out = buffer.size();
+ rc = inflate(&(zlib->stream), Z_SYNC_FLUSH);
+
+ if(rc != Z_OK && rc != Z_STREAM_END)
+ {
+ clear();
+ throw Exception("Zlib_Decompression: Error finalizing decompression");
+ }
+
+ send(buffer.begin(), buffer.size() - zlib->stream.avail_out);
+ }
+
+ clear();
+ }
+
+/*
+* Clean up Decompression Context
+*/
+void Zlib_Decompression::clear()
+ {
+ no_writes = true;
+
+ if(zlib)
+ {
+ inflateEnd(&(zlib->stream));
+ delete zlib;
+ zlib = 0;
+ }
+
+ buffer.clear();
+ }
+
+}
diff --git a/botan/src/codec/zlib/zlib.h b/botan/src/codec/zlib/zlib.h
new file mode 100644
index 0000000..4a7f3bc
--- /dev/null
+++ b/botan/src/codec/zlib/zlib.h
@@ -0,0 +1,58 @@
+/*
+* Zlib Compressor
+* (C) 2001 Peter J Jones
+* 2001-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ZLIB_H__
+#define BOTAN_ZLIB_H__
+
+#include <botan/filter.h>
+
+namespace Botan {
+
+/*
+* Zlib Compression Filter
+*/
+class BOTAN_DLL Zlib_Compression : public Filter
+ {
+ public:
+ void write(const byte input[], u32bit length);
+ void start_msg();
+ void end_msg();
+
+ void flush();
+
+ Zlib_Compression(u32bit = 6);
+ ~Zlib_Compression() { clear(); }
+ private:
+ void clear();
+ const u32bit level;
+ SecureVector<byte> buffer;
+ class Zlib_Stream* zlib;
+ };
+
+/*
+* Zlib Decompression Filter
+*/
+class BOTAN_DLL Zlib_Decompression : public Filter
+ {
+ public:
+ void write(const byte input[], u32bit length);
+ void start_msg();
+ void end_msg();
+
+ Zlib_Decompression();
+ ~Zlib_Decompression() { clear(); }
+ private:
+ void clear();
+ SecureVector<byte> buffer;
+ class Zlib_Stream* zlib;
+ bool no_writes;
+ };
+
+}
+
+#endif