aboutsummaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/base.cpp199
-rw-r--r--src/core/base.h146
-rw-r--r--src/core/botan.h11
-rw-r--r--src/core/data_src.cpp203
-rw-r--r--src/core/data_src.h78
-rw-r--r--src/core/datastor.cpp169
-rw-r--r--src/core/datastor.h59
-rw-r--r--src/core/def_alg.cpp574
-rw-r--r--src/core/def_mode.cpp177
-rw-r--r--src/core/dh_op.cpp41
-rw-r--r--src/core/dsa_op.cpp106
-rw-r--r--src/core/elg_op.cpp89
-rw-r--r--src/core/eng_base.cpp306
-rw-r--r--src/core/eng_def.h46
-rw-r--r--src/core/engine.cpp370
-rw-r--r--src/core/engine.h123
-rw-r--r--src/core/enums.h67
-rw-r--r--src/core/exceptn.cpp60
-rw-r--r--src/core/exceptn.h195
-rw-r--r--src/core/get_algo.cpp236
-rw-r--r--src/core/get_enc.cpp219
-rw-r--r--src/core/get_pbe.cpp88
-rw-r--r--src/core/init.h50
-rw-r--r--src/core/init_def.cpp60
-rw-r--r--src/core/init_opt.cpp102
-rw-r--r--src/core/kdf.cpp70
-rw-r--r--src/core/libstate.cpp294
-rw-r--r--src/core/libstate.h90
-rw-r--r--src/core/look_add.h27
-rw-r--r--src/core/look_pk.cpp74
-rw-r--r--src/core/look_pk.h38
-rw-r--r--src/core/lookup.h92
-rw-r--r--src/core/mlock.cpp24
-rw-r--r--src/core/modules.cpp127
-rw-r--r--src/core/modules.h51
-rw-r--r--src/core/mutex.h54
-rw-r--r--src/core/nr_op.cpp104
-rw-r--r--src/core/oids.cpp74
-rw-r--r--src/core/oids.h36
-rw-r--r--src/core/pk_algs.cpp98
-rw-r--r--src/core/pk_algs.h22
-rw-r--r--src/core/pk_core.cpp300
-rw-r--r--src/core/pk_core.h128
-rw-r--r--src/core/pk_keys.cpp68
-rw-r--r--src/core/pk_keys.h127
-rw-r--r--src/core/pk_ops.h79
-rw-r--r--src/core/pk_util.cpp48
-rw-r--r--src/core/pk_util.h92
-rw-r--r--src/core/pkcs8.cpp307
-rw-r--r--src/core/pkcs8.h85
-rw-r--r--src/core/policy.cpp500
-rw-r--r--src/core/pubkey.cpp415
-rw-r--r--src/core/pubkey.h210
-rw-r--r--src/core/rng.cpp144
-rw-r--r--src/core/rng.h66
-rw-r--r--src/core/rsa_op.cpp83
-rw-r--r--src/core/s2k.cpp53
-rw-r--r--src/core/s2k.h45
-rw-r--r--src/core/symkey.cpp139
-rw-r--r--src/core/symkey.h60
-rw-r--r--src/core/x509_key.cpp174
-rw-r--r--src/core/x509_key.h58
62 files changed, 8230 insertions, 0 deletions
diff --git a/src/core/base.cpp b/src/core/base.cpp
new file mode 100644
index 000000000..eb38d0c85
--- /dev/null
+++ b/src/core/base.cpp
@@ -0,0 +1,199 @@
+/*************************************************
+* Base Classes Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/base.h>
+#include <botan/version.h>
+
+namespace Botan {
+
+/*************************************************
+* SymmetricAlgorithm Constructor *
+*************************************************/
+SymmetricAlgorithm::SymmetricAlgorithm(u32bit key_min, u32bit key_max,
+ u32bit key_mod) :
+ MAXIMUM_KEYLENGTH(key_max ? key_max : key_min),
+ MINIMUM_KEYLENGTH(key_min),
+ KEYLENGTH_MULTIPLE(key_mod)
+ {
+ }
+
+/*************************************************
+* Query if the keylength is valid *
+*************************************************/
+bool SymmetricAlgorithm::valid_keylength(u32bit length) const
+ {
+ return ((length >= MINIMUM_KEYLENGTH) &&
+ (length <= MAXIMUM_KEYLENGTH) &&
+ (length % KEYLENGTH_MULTIPLE == 0));
+ }
+
+/*************************************************
+* Set the key *
+*************************************************/
+void SymmetricAlgorithm::set_key(const SymmetricKey& algo_key)
+ throw(Invalid_Key_Length)
+ {
+ set_key(algo_key.begin(), algo_key.length());
+ }
+
+/*************************************************
+* Set the key *
+*************************************************/
+void SymmetricAlgorithm::set_key(const byte algo_key[], u32bit length)
+ throw(Invalid_Key_Length)
+ {
+ if(!valid_keylength(length))
+ throw Invalid_Key_Length(name(), length);
+ key(algo_key, length);
+ }
+
+/*************************************************
+* BlockCipher Constructor *
+*************************************************/
+BlockCipher::BlockCipher(u32bit block, u32bit key_min, u32bit key_max,
+ u32bit key_mod) :
+ SymmetricAlgorithm(key_min, key_max, key_mod),
+ BLOCK_SIZE(block)
+ {
+ }
+
+/*************************************************
+* StreamCipher Constructor *
+*************************************************/
+StreamCipher::StreamCipher(u32bit key_min, u32bit key_max, u32bit key_mod,
+ u32bit iv_len) :
+ SymmetricAlgorithm(key_min, key_max, key_mod), IV_LENGTH(iv_len)
+ {
+ }
+
+/*************************************************
+* BufferedComputation Constructor *
+*************************************************/
+BufferedComputation::BufferedComputation(u32bit olen) : OUTPUT_LENGTH(olen)
+ {
+ }
+
+/*************************************************
+* HashFunction Constructor *
+*************************************************/
+HashFunction::HashFunction(u32bit hlen, u32bit blen) :
+ BufferedComputation(hlen), HASH_BLOCK_SIZE(blen)
+ {
+ }
+
+/*************************************************
+* MessageAuthenticationCode Constructor *
+*************************************************/
+MessageAuthenticationCode::MessageAuthenticationCode(u32bit mlen,
+ u32bit key_min,
+ u32bit key_max,
+ u32bit key_mod) :
+ BufferedComputation(mlen),
+ SymmetricAlgorithm(key_min, key_max, key_mod)
+ {
+ }
+
+/*************************************************
+* Default MAC verification operation *
+*************************************************/
+bool MessageAuthenticationCode::verify_mac(const byte mac[], u32bit length)
+ {
+ SecureVector<byte> our_mac = final();
+ if(our_mac.size() != length)
+ return false;
+ for(u32bit j = 0; j != length; ++j)
+ if(mac[j] != our_mac[j])
+ return false;
+ return true;
+ }
+
+/*************************************************
+* Default StreamCipher Resync Operation *
+*************************************************/
+void StreamCipher::resync(const byte[], u32bit length)
+ {
+ if(length)
+ throw Exception("The stream cipher " + name() +
+ " does not support resyncronization");
+ }
+
+/*************************************************
+* Default StreamCipher Seek Operation *
+*************************************************/
+void StreamCipher::seek(u32bit)
+ {
+ throw Exception("The stream cipher " + name() + " does not support seek()");
+ }
+
+/*************************************************
+* Hashing/MACing *
+*************************************************/
+void BufferedComputation::update(const byte in[], u32bit n)
+ {
+ add_data(in, n);
+ }
+
+/*************************************************
+* Hashing/MACing *
+*************************************************/
+void BufferedComputation::update(const MemoryRegion<byte>& in)
+ {
+ add_data(in, in.size());
+ }
+
+/*************************************************
+* Hashing/MACing *
+*************************************************/
+void BufferedComputation::update(const std::string& str)
+ {
+ update(reinterpret_cast<const byte*>(str.data()), str.size());
+ }
+
+/*************************************************
+* Hashing/MACing *
+*************************************************/
+void BufferedComputation::update(byte in)
+ {
+ update(&in, 1);
+ }
+
+/*************************************************
+* Hashing/MACing *
+*************************************************/
+SecureVector<byte> BufferedComputation::final()
+ {
+ SecureVector<byte> output(OUTPUT_LENGTH);
+ final_result(output);
+ return output;
+ }
+
+/*************************************************
+* Hashing/MACing *
+*************************************************/
+SecureVector<byte> BufferedComputation::process(const byte in[], u32bit len)
+ {
+ update(in, len);
+ return final();
+ }
+
+/*************************************************
+* Hashing/MACing *
+*************************************************/
+SecureVector<byte> BufferedComputation::process(const MemoryRegion<byte>& in)
+ {
+ update(in, in.size());
+ return final();
+ }
+
+/*************************************************
+* Hashing/MACing *
+*************************************************/
+SecureVector<byte> BufferedComputation::process(const std::string& in)
+ {
+ update(in);
+ return final();
+ }
+
+}
diff --git a/src/core/base.h b/src/core/base.h
new file mode 100644
index 000000000..b05feaacb
--- /dev/null
+++ b/src/core/base.h
@@ -0,0 +1,146 @@
+/*************************************************
+* Base Classes Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_BASE_H__
+#define BOTAN_BASE_H__
+
+#include <botan/exceptn.h>
+#include <botan/symkey.h>
+
+namespace Botan {
+
+/*************************************************
+* Constants *
+*************************************************/
+static const u32bit DEFAULT_BUFFERSIZE = BOTAN_DEFAULT_BUFFER_SIZE;
+
+/*************************************************
+* Symmetric Algorithm *
+*************************************************/
+class BOTAN_DLL SymmetricAlgorithm
+ {
+ public:
+ const u32bit MAXIMUM_KEYLENGTH, MINIMUM_KEYLENGTH, KEYLENGTH_MULTIPLE;
+
+ virtual std::string name() const = 0;
+
+ void set_key(const SymmetricKey&) throw(Invalid_Key_Length);
+ void set_key(const byte[], u32bit) throw(Invalid_Key_Length);
+ bool valid_keylength(u32bit) const;
+ SymmetricAlgorithm(u32bit, u32bit, u32bit);
+ virtual ~SymmetricAlgorithm() {}
+ private:
+ virtual void key(const byte[], u32bit) = 0;
+ };
+
+/*************************************************
+* Block Cipher *
+*************************************************/
+class BOTAN_DLL BlockCipher : public SymmetricAlgorithm
+ {
+ public:
+ const u32bit BLOCK_SIZE;
+
+ void encrypt(const byte in[], byte out[]) const { enc(in, out); }
+ void decrypt(const byte in[], byte out[]) const { dec(in, out); }
+ void encrypt(byte block[]) const { enc(block, block); }
+ void decrypt(byte block[]) const { dec(block, block); }
+
+ virtual BlockCipher* clone() const = 0;
+ virtual void clear() throw() = 0;
+
+ BlockCipher(u32bit, u32bit, u32bit = 0, u32bit = 1);
+ virtual ~BlockCipher() {}
+ private:
+ virtual void enc(const byte[], byte[]) const = 0;
+ virtual void dec(const byte[], byte[]) const = 0;
+ };
+
+/*************************************************
+* Stream Cipher *
+*************************************************/
+class BOTAN_DLL StreamCipher : public SymmetricAlgorithm
+ {
+ public:
+ const u32bit IV_LENGTH;
+ void encrypt(const byte i[], byte o[], u32bit len) { cipher(i, o, len); }
+ void decrypt(const byte i[], byte o[], u32bit len) { cipher(i, o, len); }
+ void encrypt(byte in[], u32bit len) { cipher(in, in, len); }
+ void decrypt(byte in[], u32bit len) { cipher(in, in, len); }
+
+ virtual void resync(const byte[], u32bit);
+ virtual void seek(u32bit);
+
+ virtual StreamCipher* clone() const = 0;
+ virtual void clear() throw() = 0;
+
+ StreamCipher(u32bit, u32bit = 0, u32bit = 1, u32bit = 0);
+ virtual ~StreamCipher() {}
+ private:
+ virtual void cipher(const byte[], byte[], u32bit) = 0;
+ };
+
+/*************************************************
+* Buffered Computation *
+*************************************************/
+class BOTAN_DLL BufferedComputation
+ {
+ public:
+ const u32bit OUTPUT_LENGTH;
+ void update(const byte[], u32bit);
+ void update(const MemoryRegion<byte>&);
+ void update(const std::string&);
+ void update(byte);
+ void final(byte out[]) { final_result(out); }
+ SecureVector<byte> final();
+ SecureVector<byte> process(const byte[], u32bit);
+ SecureVector<byte> process(const MemoryRegion<byte>&);
+ SecureVector<byte> process(const std::string&);
+ BufferedComputation(u32bit);
+ virtual ~BufferedComputation() {}
+ private:
+ BufferedComputation& operator=(const BufferedComputation&);
+ virtual void add_data(const byte[], u32bit) = 0;
+ virtual void final_result(byte[]) = 0;
+ };
+
+/*************************************************
+* Hash Function *
+*************************************************/
+class BOTAN_DLL HashFunction : public BufferedComputation
+ {
+ public:
+ const u32bit HASH_BLOCK_SIZE;
+
+ virtual HashFunction* clone() const = 0;
+ virtual std::string name() const = 0;
+ virtual void clear() throw() = 0;
+
+ HashFunction(u32bit, u32bit = 0);
+ virtual ~HashFunction() {}
+ private:
+ HashFunction& operator=(const HashFunction&);
+ };
+
+/*************************************************
+* Message Authentication Code *
+*************************************************/
+class BOTAN_DLL MessageAuthenticationCode : public BufferedComputation,
+ public SymmetricAlgorithm
+ {
+ public:
+ virtual bool verify_mac(const byte[], u32bit);
+
+ virtual MessageAuthenticationCode* clone() const = 0;
+ virtual std::string name() const = 0;
+ virtual void clear() throw() = 0;
+
+ MessageAuthenticationCode(u32bit, u32bit, u32bit = 0, u32bit = 1);
+ virtual ~MessageAuthenticationCode() {}
+ };
+
+}
+
+#endif
diff --git a/src/core/botan.h b/src/core/botan.h
new file mode 100644
index 000000000..70261398a
--- /dev/null
+++ b/src/core/botan.h
@@ -0,0 +1,11 @@
+/*************************************************
+* Botan Core Interface Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/base.h>
+#include <botan/rng.h>
+#include <botan/init.h>
+#include <botan/lookup.h>
+#include <botan/version.h>
+#include <botan/parsing.h>
diff --git a/src/core/data_src.cpp b/src/core/data_src.cpp
new file mode 100644
index 000000000..1ec1ae090
--- /dev/null
+++ b/src/core/data_src.cpp
@@ -0,0 +1,203 @@
+/*************************************************
+* DataSource Source File *
+* (C) 1999-2007 Jack Lloyd *
+* 2005 Matthew Gregan *
+*************************************************/
+
+#include <botan/data_src.h>
+#include <fstream>
+#include <algorithm>
+
+namespace Botan {
+
+/*************************************************
+* Read a single byte from the DataSource *
+*************************************************/
+u32bit DataSource::read_byte(byte& out)
+ {
+ return read(&out, 1);
+ }
+
+/*************************************************
+* Peek a single byte from the DataSource *
+*************************************************/
+u32bit DataSource::peek_byte(byte& out) const
+ {
+ return peek(&out, 1, 0);
+ }
+
+/*************************************************
+* Discard the next N bytes of the data *
+*************************************************/
+u32bit DataSource::discard_next(u32bit n)
+ {
+ u32bit discarded = 0;
+ byte dummy;
+ for(u32bit j = 0; j != n; ++j)
+ discarded = read_byte(dummy);
+ return discarded;
+ }
+
+/*************************************************
+* Read from a memory buffer *
+*************************************************/
+u32bit DataSource_Memory::read(byte out[], u32bit length)
+ {
+ u32bit got = std::min(source.size() - offset, length);
+ copy_mem(out, source + offset, got);
+ offset += got;
+ return got;
+ }
+
+/*************************************************
+* Peek into a memory buffer *
+*************************************************/
+u32bit DataSource_Memory::peek(byte out[], u32bit length,
+ u32bit peek_offset) const
+ {
+ const u32bit bytes_left = source.size() - offset;
+ if(peek_offset >= bytes_left) return 0;
+
+ u32bit got = std::min(bytes_left - peek_offset, length);
+ copy_mem(out, source + offset + peek_offset, got);
+ return got;
+ }
+
+/*************************************************
+* Check if the memory buffer is empty *
+*************************************************/
+bool DataSource_Memory::end_of_data() const
+ {
+ return (offset == source.size());
+ }
+
+/*************************************************
+* DataSource_Memory Constructor *
+*************************************************/
+DataSource_Memory::DataSource_Memory(const byte in[], u32bit length)
+ {
+ source.set(in, length);
+ offset = 0;
+ }
+
+/*************************************************
+* DataSource_Memory Constructor *
+*************************************************/
+DataSource_Memory::DataSource_Memory(const MemoryRegion<byte>& in)
+ {
+ source = in;
+ offset = 0;
+ }
+
+/*************************************************
+* DataSource_Memory Constructor *
+*************************************************/
+DataSource_Memory::DataSource_Memory(const std::string& in)
+ {
+ source.set(reinterpret_cast<const byte*>(in.data()), in.length());
+ offset = 0;
+ }
+
+/*************************************************
+* Read from a stream *
+*************************************************/
+u32bit DataSource_Stream::read(byte out[], u32bit length)
+ {
+ source->read(reinterpret_cast<char*>(out), length);
+ if(source->bad())
+ throw Stream_IO_Error("DataSource_Stream::read: Source failure");
+
+ u32bit got = source->gcount();
+ total_read += got;
+ return got;
+ }
+
+/*************************************************
+* Peek into a stream *
+*************************************************/
+u32bit DataSource_Stream::peek(byte out[], u32bit length, u32bit offset) const
+ {
+ if(end_of_data())
+ throw Invalid_State("DataSource_Stream: Cannot peek when out of data");
+
+ u32bit got = 0;
+
+ if(offset)
+ {
+ SecureVector<byte> buf(offset);
+ source->read(reinterpret_cast<char*>(buf.begin()), buf.size());
+ if(source->bad())
+ throw Stream_IO_Error("DataSource_Stream::peek: Source failure");
+ got = source->gcount();
+ }
+
+ if(got == offset)
+ {
+ source->read(reinterpret_cast<char*>(out), length);
+ if(source->bad())
+ throw Stream_IO_Error("DataSource_Stream::peek: Source failure");
+ got = source->gcount();
+ }
+
+ if(source->eof())
+ source->clear();
+ source->seekg(total_read, std::ios::beg);
+
+ return got;
+ }
+
+/*************************************************
+* Check if the stream is empty or in error *
+*************************************************/
+bool DataSource_Stream::end_of_data() const
+ {
+ return (!source->good());
+ }
+
+/*************************************************
+* Return a human-readable ID for this stream *
+*************************************************/
+std::string DataSource_Stream::id() const
+ {
+ return identifier;
+ }
+
+/*************************************************
+* DataSource_Stream Constructor *
+*************************************************/
+DataSource_Stream::DataSource_Stream(const std::string& path,
+ bool use_binary) :
+ identifier(path), owner(true)
+ {
+ if(use_binary)
+ source = new std::ifstream(path.c_str(), std::ios::binary);
+ else
+ source = new std::ifstream(path.c_str());
+
+ if(!source->good())
+ throw Stream_IO_Error("DataSource: Failure opening file " + path);
+
+ total_read = 0;
+ }
+
+/*************************************************
+* DataSource_Stream Constructor *
+*************************************************/
+DataSource_Stream::DataSource_Stream(std::istream& in,
+ const std::string& name) :
+ identifier(name), owner(false)
+ {
+ source = &in;
+ total_read = 0;
+ }
+
+/*************************************************
+* DataSource_Stream Destructor *
+*************************************************/
+DataSource_Stream::~DataSource_Stream()
+ {
+ if(owner)
+ delete source;
+ }
+
+}
diff --git a/src/core/data_src.h b/src/core/data_src.h
new file mode 100644
index 000000000..f7285e8fb
--- /dev/null
+++ b/src/core/data_src.h
@@ -0,0 +1,78 @@
+/*************************************************
+* DataSource Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_DATA_SRC_H__
+#define BOTAN_DATA_SRC_H__
+
+#include <botan/base.h>
+#include <iosfwd>
+
+namespace Botan {
+
+/*************************************************
+* Generic DataSource Interface *
+*************************************************/
+class BOTAN_DLL DataSource
+ {
+ public:
+ virtual u32bit read(byte[], u32bit) = 0;
+ virtual u32bit peek(byte[], u32bit, u32bit) const = 0;
+ virtual bool end_of_data() const = 0;
+ virtual std::string id() const { return ""; }
+
+ u32bit read_byte(byte&);
+ u32bit peek_byte(byte&) const;
+ u32bit discard_next(u32bit);
+
+ DataSource() {}
+ virtual ~DataSource() {}
+ private:
+ DataSource& operator=(const DataSource&) { return (*this); }
+ DataSource(const DataSource&);
+ };
+
+/*************************************************
+* 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;
+
+ DataSource_Memory(const std::string&);
+ DataSource_Memory(const byte[], u32bit);
+ DataSource_Memory(const MemoryRegion<byte>&);
+ private:
+ SecureVector<byte> source;
+ u32bit offset;
+ };
+
+/*************************************************
+* 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 = "");
+ DataSource_Stream(const std::string&, bool = false);
+ ~DataSource_Stream();
+ private:
+ const std::string identifier;
+ const bool owner;
+
+ std::istream* source;
+ u32bit total_read;
+ };
+
+}
+
+#endif
diff --git a/src/core/datastor.cpp b/src/core/datastor.cpp
new file mode 100644
index 000000000..bff6bcf5b
--- /dev/null
+++ b/src/core/datastor.cpp
@@ -0,0 +1,169 @@
+/*************************************************
+* Data Store Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/datastor.h>
+#include <botan/filters.h>
+#include <botan/parsing.h>
+#include <botan/stl_util.h>
+
+namespace Botan {
+
+/*************************************************
+* Default Matcher transform operation (identity) *
+*************************************************/
+std::pair<std::string, std::string>
+Data_Store::Matcher::transform(const std::string& key,
+ const std::string& value) const
+ {
+ return std::make_pair(key, value);
+ }
+
+/*************************************************
+* Data_Store Equality Comparison *
+*************************************************/
+bool Data_Store::operator==(const Data_Store& other) const
+ {
+ return (contents == other.contents);
+ }
+
+/*************************************************
+* Check if this key has at least one value *
+*************************************************/
+bool Data_Store::has_value(const std::string& key) const
+ {
+ return (contents.lower_bound(key) != contents.end());
+ }
+
+/*************************************************
+* Search based on an arbitrary predicate *
+*************************************************/
+std::multimap<std::string, std::string>
+Data_Store::search_with(const Matcher& matcher) const
+ {
+ std::multimap<std::string, std::string> out;
+
+ std::multimap<std::string, std::string>::const_iterator i =
+ contents.begin();
+
+ while(i != contents.end())
+ {
+ if(matcher(i->first, i->second))
+ out.insert(matcher.transform(i->first, i->second));
+ ++i;
+ }
+
+ return out;
+ }
+
+/*************************************************
+* Search based on key equality *
+*************************************************/
+std::vector<std::string> Data_Store::get(const std::string& looking_for) const
+ {
+ typedef std::multimap<std::string, std::string>::const_iterator iter;
+
+ std::pair<iter, iter> range = contents.equal_range(looking_for);
+
+ std::vector<std::string> out;
+ for(iter i = range.first; i != range.second; ++i)
+ out.push_back(i->second);
+ return out;
+ }
+
+/*************************************************
+* Get a single atom *
+*************************************************/
+std::string Data_Store::get1(const std::string& key) const
+ {
+ std::vector<std::string> vals = get(key);
+
+ if(vals.empty())
+ throw Invalid_State("Data_Store::get1: Not values for " + key);
+ if(vals.size() > 1)
+ throw Invalid_State("Data_Store::get1: More than one value for " + key);
+
+ return vals[0];
+ }
+
+/*************************************************
+* Get a single MemoryVector atom *
+*************************************************/
+MemoryVector<byte>
+Data_Store::get1_memvec(const std::string& key) const
+ {
+ std::vector<std::string> vals = get(key);
+
+ if(vals.size() > 1)
+ throw Invalid_State("Data_Store::get1_memvec: Multiple values for " +
+ key);
+
+ if(vals.empty())
+ return MemoryVector<byte>();
+
+ Pipe pipe(new Hex_Decoder(FULL_CHECK));
+ pipe.start_msg();
+ if(vals.size())
+ pipe.write(vals[0]);
+ pipe.end_msg();
+ return pipe.read_all();
+ }
+
+/*************************************************
+* Get a single u32bit atom *
+*************************************************/
+u32bit Data_Store::get1_u32bit(const std::string& key,
+ u32bit default_val) const
+ {
+ std::vector<std::string> vals = get(key);
+
+ if(vals.empty())
+ return default_val;
+ else if(vals.size() > 1)
+ throw Invalid_State("Data_Store::get1_u32bit: Multiple values for " +
+ key);
+
+ return to_u32bit(vals[0]);
+ }
+
+/*************************************************
+* Insert a single key and value *
+*************************************************/
+void Data_Store::add(const std::string& key, const std::string& val)
+ {
+ multimap_insert(contents, key, val);
+ }
+
+/*************************************************
+* Insert a single key and value *
+*************************************************/
+void Data_Store::add(const std::string& key, u32bit val)
+ {
+ add(key, to_string(val));
+ }
+
+/*************************************************
+* Insert a single key and value *
+*************************************************/
+void Data_Store::add(const std::string& key, const MemoryRegion<byte>& val)
+ {
+ Pipe pipe(new Hex_Encoder);
+ pipe.process_msg(val);
+ add(key, pipe.read_all_as_string());
+ }
+
+/*************************************************
+* Insert a mapping of key/value pairs *
+*************************************************/
+void Data_Store::add(const std::multimap<std::string, std::string>& in)
+ {
+ std::multimap<std::string, std::string>::const_iterator i = in.begin();
+ while(i != in.end())
+ {
+ contents.insert(*i);
+ ++i;
+ }
+ }
+
+}
diff --git a/src/core/datastor.h b/src/core/datastor.h
new file mode 100644
index 000000000..0f6029189
--- /dev/null
+++ b/src/core/datastor.h
@@ -0,0 +1,59 @@
+/*************************************************
+* Data Store Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_DATA_STORE_H__
+#define BOTAN_DATA_STORE_H__
+
+#include <botan/secmem.h>
+#include <utility>
+#include <string>
+#include <vector>
+#include <map>
+
+namespace Botan {
+
+/*************************************************
+* Data Store *
+*************************************************/
+class BOTAN_DLL Data_Store
+ {
+ public:
+ class BOTAN_DLL Matcher
+ {
+ public:
+ virtual bool operator()(const std::string&,
+ const std::string&) const = 0;
+
+ virtual std::pair<std::string, std::string>
+ transform(const std::string&, const std::string&) const;
+
+ virtual ~Matcher() {}
+ };
+
+ bool operator==(const Data_Store&) const;
+
+ std::multimap<std::string, std::string>
+ search_with(const Matcher&) const;
+
+ std::vector<std::string> get(const std::string&) const;
+
+ std::string get1(const std::string&) const;
+
+ MemoryVector<byte> get1_memvec(const std::string&) const;
+ u32bit get1_u32bit(const std::string&, u32bit = 0) const;
+
+ bool has_value(const std::string&) const;
+
+ void add(const std::multimap<std::string, std::string>&);
+ void add(const std::string&, const std::string&);
+ void add(const std::string&, u32bit);
+ void add(const std::string&, const MemoryRegion<byte>&);
+ private:
+ std::multimap<std::string, std::string> contents;
+ };
+
+}
+
+#endif
diff --git a/src/core/def_alg.cpp b/src/core/def_alg.cpp
new file mode 100644
index 000000000..b13439fe2
--- /dev/null
+++ b/src/core/def_alg.cpp
@@ -0,0 +1,574 @@
+/*************************************************
+* Default Engine Algorithms Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/eng_def.h>
+#include <botan/libstate.h>
+#include <botan/parsing.h>
+
+#if defined(BOTAN_HAS_AES)
+ #include <botan/aes.h>
+#endif
+
+#if defined(BOTAN_HAS_BLOWFISH)
+ #include <botan/blowfish.h>
+#endif
+
+#if defined(BOTAN_HAS_CAST)
+ #include <botan/cast128.h>
+ #include <botan/cast256.h>
+#endif
+
+#if defined(BOTAN_HAS_DES)
+ #include <botan/des.h>
+#endif
+
+#if defined(BOTAN_HAS_GOST)
+ #include <botan/gost.h>
+#endif
+
+#if defined(BOTAN_HAS_IDEA)
+ #include <botan/idea.h>
+#endif
+
+#if defined(BOTAN_HAS_KASUMI)
+ #include <botan/kasumi.h>
+#endif
+
+#if defined(BOTAN_HAS_LION)
+ #include <botan/lion.h>
+#endif
+
+#if defined(BOTAN_HAS_LUBY_RACKOFF)
+ #include <botan/lubyrack.h>
+#endif
+
+#if defined(BOTAN_HAS_MARS)
+ #include <botan/mars.h>
+#endif
+
+#if defined(BOTAN_HAS_MISTY1)
+ #include <botan/misty1.h>
+#endif
+
+#if defined(BOTAN_HAS_NOEKEON)
+ #include <botan/noekeon.h>
+#endif
+
+#if defined(BOTAN_HAS_RC2)
+ #include <botan/rc2.h>
+#endif
+
+#if defined(BOTAN_HAS_RC5)
+ #include <botan/rc5.h>
+#endif
+
+#if defined(BOTAN_HAS_RC6)
+ #include <botan/rc6.h>
+#endif
+
+#if defined(BOTAN_HAS_SAFER)
+ #include <botan/safer_sk.h>
+#endif
+
+#if defined(BOTAN_HAS_SEED)
+ #include <botan/seed.h>
+#endif
+
+#if defined(BOTAN_HAS_SERPENT)
+ #include <botan/serpent.h>
+#endif
+
+#if defined(BOTAN_HAS_SKIPJACK)
+ #include <botan/skipjack.h>
+#endif
+
+#if defined(BOTAN_HAS_SQUARE)
+ #include <botan/square.h>
+#endif
+
+#if defined(BOTAN_HAS_TEA)
+ #include <botan/tea.h>
+#endif
+
+#if defined(BOTAN_HAS_TWOFISH)
+ #include <botan/twofish.h>
+#endif
+
+#if defined(BOTAN_HAS_XTEA)
+ #include <botan/xtea.h>
+#endif
+
+#if defined(BOTAN_HAS_ARC4)
+ #include <botan/arc4.h>
+#endif
+
+#if defined(BOTAN_HAS_SALSA20)
+ #include <botan/salsa20.h>
+#endif
+
+#if defined(BOTAN_HAS_TURING)
+ #include <botan/turing.h>
+#endif
+
+#if defined(BOTAN_HAS_WID_WAKE)
+ #include <botan/wid_wake.h>
+#endif
+
+#if defined(BOTAN_HAS_CIPHER_MODE_PADDING)
+ #include <botan/mode_pad.h>
+#endif
+
+#if defined(BOTAN_HAS_ADLER32)
+ #include <botan/adler32.h>
+#endif
+
+#if defined(BOTAN_HAS_CRC24)
+ #include <botan/crc24.h>
+#endif
+
+#if defined(BOTAN_HAS_CRC32)
+ #include <botan/crc32.h>
+#endif
+
+#if defined(BOTAN_HAS_FORK_256)
+ #include <botan/fork256.h>
+#endif
+
+#if defined(BOTAN_HAS_HAS_160)
+ #include <botan/has160.h>
+#endif
+
+#if defined(BOTAN_HAS_MD2)
+ #include <botan/md2.h>
+#endif
+
+#if defined(BOTAN_HAS_MD4)
+ #include <botan/md4.h>
+#endif
+
+#if defined(BOTAN_HAS_MD5)
+ #include <botan/md5.h>
+#endif
+
+#if defined(BOTAN_HAS_RIPEMD_128)
+ #include <botan/rmd128.h>
+#endif
+
+#if defined(BOTAN_HAS_RIPEMD_160)
+ #include <botan/rmd160.h>
+#endif
+
+#if defined(BOTAN_HAS_SHA1)
+ #include <botan/sha160.h>
+#endif
+
+#if defined(BOTAN_HAS_SHA2)
+ #include <botan/sha256.h>
+ #include <botan/sha_64.h>
+#endif
+
+#if defined(BOTAN_HAS_TIGER)
+ #include <botan/tiger.h>
+#endif
+
+#if defined(BOTAN_HAS_WHIRLPOOL)
+ #include <botan/whrlpool.h>
+#endif
+
+#if defined(BOTAN_HAS_PARALLEL_HASH)
+ #include <botan/par_hash.h>
+#endif
+
+#if defined(BOTAN_HAS_CBC_MAC)
+ #include <botan/cbc_mac.h>
+#endif
+
+#if defined(BOTAN_HAS_CMAC)
+ #include <botan/cmac.h>
+#endif
+
+#if defined(BOTAN_HAS_HMAC)
+ #include <botan/hmac.h>
+#endif
+
+#if defined(BOTAN_HAS_SSL3_MAC)
+ #include <botan/ssl3_mac.h>
+#endif
+
+#if defined(BOTAN_HAS_ANSI_X919_MAC)
+ #include <botan/x919_mac.h>
+#endif
+
+#if defined(BOTAN_HAS_PBKDF1)
+ #include <botan/pbkdf1.h>
+#endif
+
+#if defined(BOTAN_HAS_PBKDF2)
+ #include <botan/pbkdf2.h>
+#endif
+
+#if defined(BOTAN_HAS_PGPS2K)
+ #include <botan/pgp_s2k.h>
+#endif
+
+namespace Botan {
+
+/*************************************************
+* Some macros to simplify control flow *
+*************************************************/
+#define HANDLE_TYPE_NO_ARGS(NAME, TYPE) \
+ if(algo_name == NAME) \
+ { \
+ if(name.size() == 1) \
+ return new TYPE; \
+ throw Invalid_Algorithm_Name(algo_spec); \
+ }
+
+#define HANDLE_TYPE_ONE_U32BIT(NAME, TYPE, DEFAULT) \
+ if(algo_name == NAME) \
+ { \
+ if(name.size() == 1) \
+ return new TYPE(DEFAULT); \
+ if(name.size() == 2) \
+ return new TYPE(to_u32bit(name[1])); \
+ throw Invalid_Algorithm_Name(algo_spec); \
+ }
+
+#define HANDLE_TYPE_TWO_U32BIT(NAME, TYPE, DEFAULT) \
+ if(algo_name == NAME) \
+ { \
+ if(name.size() == 1) \
+ return new TYPE(DEFAULT); \
+ if(name.size() == 2) \
+ return new TYPE(to_u32bit(name[1])); \
+ if(name.size() == 3) \
+ return new TYPE(to_u32bit(name[1]), to_u32bit(name[2])); \
+ throw Invalid_Algorithm_Name(algo_spec); \
+ }
+
+#define HANDLE_TYPE_ONE_STRING(NAME, TYPE) \
+ if(algo_name == NAME) \
+ { \
+ if(name.size() == 2) \
+ return new TYPE(name[1]); \
+ throw Invalid_Algorithm_Name(algo_spec); \
+ }
+
+/*************************************************
+* Look for an algorithm with this name *
+*************************************************/
+BlockCipher*
+Default_Engine::find_block_cipher(const std::string& algo_spec) const
+ {
+ std::vector<std::string> name = parse_algorithm_name(algo_spec);
+ if(name.empty())
+ return 0;
+ const std::string algo_name = global_state().deref_alias(name[0]);
+
+#if defined(BOTAN_HAS_AES)
+ HANDLE_TYPE_NO_ARGS("AES", AES);
+ HANDLE_TYPE_NO_ARGS("AES-128", AES_128);
+ HANDLE_TYPE_NO_ARGS("AES-192", AES_192);
+ HANDLE_TYPE_NO_ARGS("AES-256", AES_256);
+#endif
+
+#if defined(BOTAN_HAS_BLOWFISH)
+ HANDLE_TYPE_NO_ARGS("Blowfish", Blowfish);
+#endif
+
+#if defined(BOTAN_HAS_CAST)
+ HANDLE_TYPE_NO_ARGS("CAST-128", CAST_128);
+ HANDLE_TYPE_NO_ARGS("CAST-256", CAST_256);
+#endif
+
+#if defined(BOTAN_HAS_DES)
+ HANDLE_TYPE_NO_ARGS("DES", DES);
+ HANDLE_TYPE_NO_ARGS("DESX", DESX);
+ HANDLE_TYPE_NO_ARGS("TripleDES", TripleDES);
+#endif
+
+#if defined(BOTAN_HAS_GOST)
+ HANDLE_TYPE_NO_ARGS("GOST", GOST);
+#endif
+
+#if defined(BOTAN_HAS_IDEA)
+ HANDLE_TYPE_NO_ARGS("IDEA", IDEA);
+#endif
+
+#if defined(BOTAN_HAS_KASUMI)
+ HANDLE_TYPE_NO_ARGS("KASUMI", KASUMI);
+#endif
+
+#if defined(BOTAN_HAS_MARS)
+ HANDLE_TYPE_NO_ARGS("MARS", MARS);
+#endif
+
+#if defined(BOTAN_HAS_MISTY1)
+ HANDLE_TYPE_ONE_U32BIT("MISTY1", MISTY1, 8);
+#endif
+
+#if defined(BOTAN_HAS_NOEKEON)
+ HANDLE_TYPE_NO_ARGS("Noekeon", Noekeon);
+#endif
+
+#if defined(BOTAN_HAS_RC2)
+ HANDLE_TYPE_NO_ARGS("RC2", RC2);
+#endif
+
+#if defined(BOTAN_HAS_RC5)
+ HANDLE_TYPE_ONE_U32BIT("RC5", RC5, 12);
+#endif
+
+#if defined(BOTAN_HAS_RC6)
+ HANDLE_TYPE_NO_ARGS("RC6", RC6);
+#endif
+
+#if defined(BOTAN_HAS_SAFER)
+ HANDLE_TYPE_ONE_U32BIT("SAFER-SK", SAFER_SK, 10);
+#endif
+
+#if defined(BOTAN_HAS_SEED)
+ HANDLE_TYPE_NO_ARGS("SEED", SEED);
+#endif
+
+#if defined(BOTAN_HAS_SERPENT)
+ HANDLE_TYPE_NO_ARGS("Serpent", Serpent);
+#endif
+
+#if defined(BOTAN_HAS_SKIPJACK)
+ HANDLE_TYPE_NO_ARGS("Skipjack", Skipjack);
+#endif
+
+#if defined(BOTAN_HAS_SQUARE)
+ HANDLE_TYPE_NO_ARGS("Square", Square);
+#endif
+
+#if defined(BOTAN_HAS_TEA)
+ HANDLE_TYPE_NO_ARGS("TEA", TEA);
+#endif
+
+#if defined(BOTAN_HAS_TWOFISH)
+ HANDLE_TYPE_NO_ARGS("Twofish", Twofish);
+#endif
+
+#if defined(BOTAN_HAS_XTEA)
+ HANDLE_TYPE_NO_ARGS("XTEA", XTEA);
+#endif
+
+#if defined(BOTAN_HAS_LUBY_RACKOFF)
+ if(algo_name == "Luby-Rackoff" && name.size() >= 2)
+ {
+ HashFunction* hash = find_hash(name[1]);
+ if(hash)
+ return new LubyRackoff(hash);
+ }
+#endif
+
+#if defined(BOTAN_HAS_LION)
+ if(algo_name == "Lion")
+ {
+ if(name.size() != 4)
+ throw Invalid_Algorithm_Name(algo_spec);
+ return new Lion(name[1], name[2], to_u32bit(name[3]));
+ }
+#endif
+
+ return 0;
+ }
+
+/*************************************************
+* Look for an algorithm with this name *
+*************************************************/
+StreamCipher*
+Default_Engine::find_stream_cipher(const std::string& algo_spec) const
+ {
+ std::vector<std::string> name = parse_algorithm_name(algo_spec);
+ if(name.empty())
+ return 0;
+ const std::string algo_name = global_state().deref_alias(name[0]);
+
+#if defined(BOTAN_HAS_ARC4)
+ HANDLE_TYPE_ONE_U32BIT("ARC4", ARC4, 0);
+ HANDLE_TYPE_ONE_U32BIT("RC4_drop", ARC4, 768);
+#endif
+
+#if defined(BOTAN_HAS_SALSA20)
+ HANDLE_TYPE_NO_ARGS("Salsa20", Salsa20);
+#endif
+
+#if defined(BOTAN_HAS_TURING)
+ HANDLE_TYPE_NO_ARGS("Turing", Turing);
+#endif
+
+#if defined(BOTAN_HAS_WID_WAKE)
+ HANDLE_TYPE_NO_ARGS("WiderWake4+1-BE", WiderWake_41_BE);
+#endif
+
+ return 0;
+ }
+
+/*************************************************
+* Look for an algorithm with this name *
+*************************************************/
+HashFunction*
+Default_Engine::find_hash(const std::string& algo_spec) const
+ {
+ std::vector<std::string> name = parse_algorithm_name(algo_spec);
+ if(name.empty())
+ return 0;
+ const std::string algo_name = global_state().deref_alias(name[0]);
+
+#if defined(BOTAN_HAS_ADLER32)
+ HANDLE_TYPE_NO_ARGS("Adler32", Adler32);
+#endif
+
+#if defined(BOTAN_HAS_CRC24)
+ HANDLE_TYPE_NO_ARGS("CRC24", CRC24);
+#endif
+
+#if defined(BOTAN_HAS_CRC32)
+ HANDLE_TYPE_NO_ARGS("CRC32", CRC32);
+#endif
+
+#if defined(BOTAN_HAS_FORK_256)
+ HANDLE_TYPE_NO_ARGS("FORK-256", FORK_256);
+#endif
+
+#if defined(BOTAN_HAS_HAS_160)
+ HANDLE_TYPE_NO_ARGS("HAS-160", HAS_160);
+#endif
+
+#if defined(BOTAN_HAS_MD2)
+ HANDLE_TYPE_NO_ARGS("MD2", MD2);
+#endif
+
+#if defined(BOTAN_HAS_MD4)
+ HANDLE_TYPE_NO_ARGS("MD4", MD4);
+#endif
+
+#if defined(BOTAN_HAS_MD5)
+ HANDLE_TYPE_NO_ARGS("MD5", MD5);
+#endif
+
+#if defined(BOTAN_HAS_RIPEMD_128)
+ HANDLE_TYPE_NO_ARGS("RIPEMD-128", RIPEMD_128);
+#endif
+
+#if defined(BOTAN_HAS_RIPEMD_160)
+ HANDLE_TYPE_NO_ARGS("RIPEMD-160", RIPEMD_160);
+#endif
+
+#if defined(BOTAN_HAS_SHA1)
+ HANDLE_TYPE_NO_ARGS("SHA-160", SHA_160);
+#endif
+
+#if defined(BOTAN_HAS_SHA2)
+ HANDLE_TYPE_NO_ARGS("SHA-256", SHA_256);
+ HANDLE_TYPE_NO_ARGS("SHA-384", SHA_384);
+ HANDLE_TYPE_NO_ARGS("SHA-512", SHA_512);
+#endif
+
+#if defined(BOTAN_HAS_TIGER)
+ HANDLE_TYPE_TWO_U32BIT("Tiger", Tiger, 24);
+#endif
+
+#if defined(BOTAN_HAS_WHIRLPOOL)
+ HANDLE_TYPE_NO_ARGS("Whirlpool", Whirlpool);
+#endif
+
+ if(algo_name == "Parallel")
+ {
+ if(name.size() < 2)
+ throw Invalid_Algorithm_Name(algo_spec);
+ name.erase(name.begin());
+ return new Parallel(name);
+ }
+
+ return 0;
+ }
+
+/*************************************************
+* Look for an algorithm with this name *
+*************************************************/
+MessageAuthenticationCode*
+Default_Engine::find_mac(const std::string& algo_spec) const
+ {
+ std::vector<std::string> name = parse_algorithm_name(algo_spec);
+ if(name.empty())
+ return 0;
+ const std::string algo_name = global_state().deref_alias(name[0]);
+
+#if defined(BOTAN_HAS_CBC_MAC)
+ HANDLE_TYPE_ONE_STRING("CBC-MAC", CBC_MAC);
+#endif
+
+#if defined(BOTAN_HAS_CMAC)
+ HANDLE_TYPE_ONE_STRING("CMAC", CMAC);
+#endif
+
+#if defined(BOTAN_HAS_HMAC)
+ HANDLE_TYPE_ONE_STRING("HMAC", HMAC);
+#endif
+
+#if defined(BOTAN_HAS_SSL3_MAC)
+ HANDLE_TYPE_ONE_STRING("SSL3-MAC", SSL3_MAC);
+#endif
+
+#if defined(BOTAN_HAS_ANSI_X919_MAC)
+ HANDLE_TYPE_NO_ARGS("X9.19-MAC", ANSI_X919_MAC);
+#endif
+
+ return 0;
+ }
+
+/*************************************************
+* Look for an algorithm with this name *
+*************************************************/
+S2K* Default_Engine::find_s2k(const std::string& algo_spec) const
+ {
+ std::vector<std::string> name = parse_algorithm_name(algo_spec);
+ if(name.empty())
+ return 0;
+
+ const std::string algo_name = global_state().deref_alias(name[0]);
+
+#if defined(BOTAN_HAS_PBKDF1)
+ HANDLE_TYPE_ONE_STRING("PBKDF1", PKCS5_PBKDF1);
+#endif
+
+#if defined(BOTAN_HAS_PBKDF2)
+ HANDLE_TYPE_ONE_STRING("PBKDF2", PKCS5_PBKDF2);
+#endif
+
+#if defined(BOTAN_HAS_PGPS2K)
+ HANDLE_TYPE_ONE_STRING("OpenPGP-S2K", OpenPGP_S2K);
+#endif
+
+ return 0;
+ }
+
+/*************************************************
+* Look for an algorithm with this name *
+*************************************************/
+BlockCipherModePaddingMethod*
+Default_Engine::find_bc_pad(const std::string& algo_spec) const
+ {
+ std::vector<std::string> name = parse_algorithm_name(algo_spec);
+ if(name.empty())
+ return 0;
+
+ const std::string algo_name = global_state().deref_alias(name[0]);
+
+#if defined(BOTAN_HAS_CIPHER_MODE_PADDING)
+ HANDLE_TYPE_NO_ARGS("PKCS7", PKCS7_Padding);
+ HANDLE_TYPE_NO_ARGS("OneAndZeros", OneAndZeros_Padding);
+ HANDLE_TYPE_NO_ARGS("X9.23", ANSI_X923_Padding);
+ HANDLE_TYPE_NO_ARGS("NoPadding", Null_Padding);
+#endif
+
+ return 0;
+ }
+
+}
diff --git a/src/core/def_mode.cpp b/src/core/def_mode.cpp
new file mode 100644
index 000000000..b062cc34b
--- /dev/null
+++ b/src/core/def_mode.cpp
@@ -0,0 +1,177 @@
+/*************************************************
+* Default Engine Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/eng_def.h>
+#include <botan/parsing.h>
+#include <botan/filters.h>
+#include <botan/lookup.h>
+
+#if defined(BOTAN_HAS_ECB)
+ #include <botan/ecb.h>
+#endif
+
+#if defined(BOTAN_HAS_CBC)
+ #include <botan/cbc.h>
+#endif
+
+#if defined(BOTAN_HAS_CTS)
+ #include <botan/cts.h>
+#endif
+
+#if defined(BOTAN_HAS_CFB)
+ #include <botan/cfb.h>
+#endif
+
+#if defined(BOTAN_HAS_OFB)
+ #include <botan/ofb.h>
+#endif
+
+#if defined(BOTAN_HAS_CTR)
+ #include <botan/ctr.h>
+#endif
+
+#if defined(BOTAN_HAS_EAX)
+ #include <botan/eax.h>
+#endif
+
+namespace Botan {
+
+/*************************************************
+* Get a cipher object *
+*************************************************/
+Keyed_Filter* Default_Engine::get_cipher(const std::string& algo_spec,
+ Cipher_Dir direction)
+ {
+ std::vector<std::string> algo_parts = split_on(algo_spec, '/');
+ if(algo_parts.empty())
+ throw Invalid_Algorithm_Name(algo_spec);
+
+ const std::string cipher = algo_parts[0];
+
+ if(have_stream_cipher(cipher))
+ {
+ if(algo_parts.size() == 1)
+ return new StreamCipher_Filter(cipher);
+ return 0;
+ }
+ else if(have_block_cipher(cipher))
+ {
+ if(algo_parts.size() != 2 && algo_parts.size() != 3)
+ return 0;
+
+ std::string mode = algo_parts[1];
+ u32bit bits = 0;
+
+ if(mode.find("CFB") != std::string::npos ||
+ mode.find("EAX") != std::string::npos)
+ {
+ std::vector<std::string> algo_info = parse_algorithm_name(mode);
+ mode = algo_info[0];
+ if(algo_info.size() == 1)
+ bits = 8*block_size_of(cipher);
+ else if(algo_info.size() == 2)
+ bits = to_u32bit(algo_info[1]);
+ else
+ throw Invalid_Algorithm_Name(algo_spec);
+ }
+
+ std::string padding;
+ if(algo_parts.size() == 3)
+ padding = algo_parts[2];
+ else
+ padding = (mode == "CBC") ? "PKCS7" : "NoPadding";
+
+ if(mode == "ECB" && padding == "CTS")
+ return 0;
+ else if((mode != "CBC" && mode != "ECB") && padding != "NoPadding")
+ throw Invalid_Algorithm_Name(algo_spec);
+
+ if(mode == "OFB")
+ {
+#if defined(BOTAN_HAS_OFB)
+ return new OFB(cipher);
+#else
+ return 0;
+#endif
+ }
+ else if(mode == "CTR-BE")
+ {
+#if defined(BOTAN_HAS_CTR)
+ return new CTR_BE(cipher);
+#else
+ return 0;
+#endif
+ }
+ else if(mode == "ECB" || mode == "CBC" || mode == "CTS" ||
+ mode == "CFB" || mode == "EAX")
+ {
+ if(mode == "ECB")
+ {
+#if defined(BOTAN_HAS_ECB)
+ if(direction == ENCRYPTION)
+ return new ECB_Encryption(cipher, padding);
+ else
+ return new ECB_Decryption(cipher, padding);
+#else
+ return 0;
+#endif
+ }
+ else if(mode == "CFB")
+ {
+#if defined(BOTAN_HAS_CFB)
+ if(direction == ENCRYPTION)
+ return new CFB_Encryption(cipher, bits);
+ else
+ return new CFB_Decryption(cipher, bits);
+#else
+ return 0;
+#endif
+ }
+ else if(mode == "CBC")
+ {
+ if(padding == "CTS")
+ {
+#if defined(BOTAN_HAS_CTS)
+ if(direction == ENCRYPTION)
+ return new CTS_Encryption(cipher);
+ else
+ return new CTS_Decryption(cipher);
+#else
+ return 0;
+#endif
+ }
+
+#if defined(BOTAN_HAS_CBC)
+ if(direction == ENCRYPTION)
+ return new CBC_Encryption(cipher, padding);
+ else
+ return new CBC_Decryption(cipher, padding);
+#else
+ return 0;
+#endif
+ }
+ else if(mode == "EAX")
+ {
+#if defined(BOTAN_HAS_EAX)
+ if(direction == ENCRYPTION)
+ return new EAX_Encryption(cipher, bits);
+ else
+ return new EAX_Decryption(cipher, bits);
+#else
+ return 0;
+#endif
+ }
+ else
+ throw Internal_Error("get_mode: " + cipher + "/"
+ + mode + "/" + padding);
+ }
+ else
+ return 0;
+ }
+
+ return 0;
+ }
+
+}
diff --git a/src/core/dh_op.cpp b/src/core/dh_op.cpp
new file mode 100644
index 000000000..0bcfd4ef8
--- /dev/null
+++ b/src/core/dh_op.cpp
@@ -0,0 +1,41 @@
+/*************************************************
+* DH Operations Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/eng_def.h>
+#include <botan/pow_mod.h>
+#include <botan/numthry.h>
+#include <botan/reducer.h>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* Default DH Operation *
+*************************************************/
+class Default_DH_Op : public DH_Operation
+ {
+ public:
+ BigInt agree(const BigInt& i) const { return powermod_x_p(i); }
+ DH_Operation* clone() const { return new Default_DH_Op(*this); }
+
+ Default_DH_Op(const DL_Group& group, const BigInt& x) :
+ powermod_x_p(x, group.get_p()) {}
+ private:
+ const Fixed_Exponent_Power_Mod powermod_x_p;
+ };
+
+}
+
+/*************************************************
+* Acquire a DH op *
+*************************************************/
+DH_Operation* Default_Engine::dh_op(const DL_Group& group,
+ const BigInt& x) const
+ {
+ return new Default_DH_Op(group, x);
+ }
+
+}
diff --git a/src/core/dsa_op.cpp b/src/core/dsa_op.cpp
new file mode 100644
index 000000000..ee94cb256
--- /dev/null
+++ b/src/core/dsa_op.cpp
@@ -0,0 +1,106 @@
+/*************************************************
+* DSA Operations Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/eng_def.h>
+#include <botan/pow_mod.h>
+#include <botan/numthry.h>
+#include <botan/reducer.h>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* Default DSA Operation *
+*************************************************/
+class Default_DSA_Op : public DSA_Operation
+ {
+ public:
+ bool verify(const byte[], u32bit, const byte[], u32bit) const;
+ SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const;
+
+ DSA_Operation* clone() const { return new Default_DSA_Op(*this); }
+
+ Default_DSA_Op(const DL_Group&, const BigInt&, const BigInt&);
+ private:
+ const BigInt x, y;
+ const DL_Group group;
+ Fixed_Base_Power_Mod powermod_g_p, powermod_y_p;
+ Modular_Reducer mod_p, mod_q;
+ };
+
+/*************************************************
+* Default_DSA_Op Constructor *
+*************************************************/
+Default_DSA_Op::Default_DSA_Op(const DL_Group& grp, const BigInt& y1,
+ const BigInt& x1) : x(x1), y(y1), group(grp)
+ {
+ powermod_g_p = Fixed_Base_Power_Mod(group.get_g(), group.get_p());
+ powermod_y_p = Fixed_Base_Power_Mod(y, group.get_p());
+ mod_p = Modular_Reducer(group.get_p());
+ mod_q = Modular_Reducer(group.get_q());
+ }
+
+/*************************************************
+* Default DSA Verify Operation *
+*************************************************/
+bool Default_DSA_Op::verify(const byte msg[], u32bit msg_len,
+ const byte sig[], u32bit sig_len) const
+ {
+ const BigInt& q = group.get_q();
+
+ if(sig_len != 2*q.bytes() || msg_len > q.bytes())
+ return false;
+
+ BigInt r(sig, q.bytes());
+ BigInt s(sig + q.bytes(), q.bytes());
+ BigInt i(msg, msg_len);
+
+ if(r <= 0 || r >= q || s <= 0 || s >= q)
+ return false;
+
+ s = inverse_mod(s, q);
+ s = mod_p.multiply(powermod_g_p(mod_q.multiply(s, i)),
+ powermod_y_p(mod_q.multiply(s, r)));
+
+ return (mod_q.reduce(s) == r);
+ }
+
+/*************************************************
+* Default DSA Sign Operation *
+*************************************************/
+SecureVector<byte> Default_DSA_Op::sign(const byte in[], u32bit length,
+ const BigInt& k) const
+ {
+ if(x == 0)
+ throw Internal_Error("Default_DSA_Op::sign: No private key");
+
+ const BigInt& q = group.get_q();
+ BigInt i(in, length);
+
+ BigInt r = mod_q.reduce(powermod_g_p(k));
+ BigInt s = mod_q.multiply(inverse_mod(k, q), mul_add(x, r, i));
+
+ if(r.is_zero() || s.is_zero())
+ throw Internal_Error("Default_DSA_Op::sign: r or s was zero");
+
+ SecureVector<byte> output(2*q.bytes());
+ r.binary_encode(output + (output.size() / 2 - r.bytes()));
+ s.binary_encode(output + (output.size() - s.bytes()));
+ return output;
+ }
+
+}
+
+/*************************************************
+* Acquire a DSA op *
+*************************************************/
+DSA_Operation* Default_Engine::dsa_op(const DL_Group& group, const BigInt& y,
+ const BigInt& x) const
+ {
+ return new Default_DSA_Op(group, y, x);
+ }
+
+}
diff --git a/src/core/elg_op.cpp b/src/core/elg_op.cpp
new file mode 100644
index 000000000..0d852d145
--- /dev/null
+++ b/src/core/elg_op.cpp
@@ -0,0 +1,89 @@
+/*************************************************
+* ElGamal Operations Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/eng_def.h>
+#include <botan/pow_mod.h>
+#include <botan/numthry.h>
+#include <botan/reducer.h>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* Default ElGamal Operation *
+*************************************************/
+class Default_ELG_Op : public ELG_Operation
+ {
+ public:
+ SecureVector<byte> encrypt(const byte[], u32bit, const BigInt&) const;
+ BigInt decrypt(const BigInt&, const BigInt&) const;
+
+ ELG_Operation* clone() const { return new Default_ELG_Op(*this); }
+
+ Default_ELG_Op(const DL_Group&, const BigInt&, const BigInt&);
+ private:
+ const BigInt p;
+ Fixed_Base_Power_Mod powermod_g_p, powermod_y_p;
+ Fixed_Exponent_Power_Mod powermod_x_p;
+ Modular_Reducer mod_p;
+ };
+
+/*************************************************
+* Default_ELG_Op Constructor *
+*************************************************/
+Default_ELG_Op::Default_ELG_Op(const DL_Group& group, const BigInt& y,
+ const BigInt& x) : p(group.get_p())
+ {
+ powermod_g_p = Fixed_Base_Power_Mod(group.get_g(), p);
+ powermod_y_p = Fixed_Base_Power_Mod(y, p);
+ mod_p = Modular_Reducer(p);
+
+ if(x != 0)
+ powermod_x_p = Fixed_Exponent_Power_Mod(x, p);
+ }
+
+/*************************************************
+* Default ElGamal Encrypt Operation *
+*************************************************/
+SecureVector<byte> Default_ELG_Op::encrypt(const byte in[], u32bit length,
+ const BigInt& k) const
+ {
+ BigInt m(in, length);
+ if(m >= p)
+ throw Invalid_Argument("Default_ELG_Op::encrypt: Input is too large");
+
+ BigInt a = powermod_g_p(k);
+ BigInt b = mod_p.multiply(m, powermod_y_p(k));
+
+ SecureVector<byte> output(2*p.bytes());
+ a.binary_encode(output + (p.bytes() - a.bytes()));
+ b.binary_encode(output + output.size() / 2 + (p.bytes() - b.bytes()));
+ return output;
+ }
+
+/*************************************************
+* Default ElGamal Decrypt Operation *
+*************************************************/
+BigInt Default_ELG_Op::decrypt(const BigInt& a, const BigInt& b) const
+ {
+ if(a >= p || b >= p)
+ throw Invalid_Argument("Default_ELG_Op: Invalid message");
+
+ return mod_p.multiply(b, inverse_mod(powermod_x_p(a), p));
+ }
+
+}
+
+/*************************************************
+* Acquire an ElGamal op *
+*************************************************/
+ELG_Operation* Default_Engine::elg_op(const DL_Group& group, const BigInt& y,
+ const BigInt& x) const
+ {
+ return new Default_ELG_Op(group, y, x);
+ }
+
+}
diff --git a/src/core/eng_base.cpp b/src/core/eng_base.cpp
new file mode 100644
index 000000000..38234d462
--- /dev/null
+++ b/src/core/eng_base.cpp
@@ -0,0 +1,306 @@
+/*************************************************
+* Basic No-Op Engine Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/engine.h>
+#include <botan/libstate.h>
+#include <botan/stl_util.h>
+#include <botan/lookup.h>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* Algorithm Cache *
+*************************************************/
+template<typename T>
+class Algorithm_Cache_Impl : public Engine::Algorithm_Cache<T>
+ {
+ public:
+ T* get(const std::string& name) const
+ {
+ Mutex_Holder lock(mutex);
+ return search_map(mappings, name);
+ }
+
+ void add(T* algo, const std::string& index_name = "") const
+ {
+ if(!algo)
+ return;
+
+ Mutex_Holder lock(mutex);
+
+ const std::string name =
+ (index_name != "" ? index_name : algo->name());
+
+ if(mappings.find(name) != mappings.end())
+ delete mappings[name];
+ mappings[name] = algo;
+ }
+
+ Algorithm_Cache_Impl()
+ {
+ mutex = global_state().get_mutex();
+ }
+
+ ~Algorithm_Cache_Impl()
+ {
+ typename std::map<std::string, T*>::iterator i = mappings.begin();
+
+ while(i != mappings.end())
+ {
+ delete i->second;
+ ++i;
+ }
+ delete mutex;
+ }
+ private:
+ Mutex* mutex;
+ mutable std::map<std::string, T*> mappings;
+ };
+
+}
+
+/*************************************************
+* Basic No-Op Engine Implementation *
+*************************************************/
+IF_Operation* Engine::if_op(const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&) const
+ {
+ return 0;
+ }
+
+/*************************************************
+* Basic No-Op Engine Implementation *
+*************************************************/
+DSA_Operation* Engine::dsa_op(const DL_Group&, const BigInt&,
+ const BigInt&) const
+ {
+ return 0;
+ }
+
+/*************************************************
+* Basic No-Op Engine Implementation *
+*************************************************/
+NR_Operation* Engine::nr_op(const DL_Group&, const BigInt&,
+ const BigInt&) const
+ {
+ return 0;
+ }
+
+/*************************************************
+* Basic No-Op Engine Implementation *
+*************************************************/
+ELG_Operation* Engine::elg_op(const DL_Group&, const BigInt&,
+ const BigInt&) const
+ {
+ return 0;
+ }
+
+/*************************************************
+* Basic No-Op Engine Implementation *
+*************************************************/
+DH_Operation* Engine::dh_op(const DL_Group&, const BigInt&) const
+ {
+ return 0;
+ }
+
+/*************************************************
+* Basic No-Op Engine Implementation *
+*************************************************/
+Modular_Exponentiator* Engine::mod_exp(const BigInt&,
+ Power_Mod::Usage_Hints) const
+ {
+ return 0;
+ }
+
+/*************************************************
+* Acquire a BlockCipher *
+*************************************************/
+const BlockCipher* Engine::block_cipher(const std::string& name) const
+ {
+ return lookup_algo(cache_of_bc, global_state().deref_alias(name),
+ this, &Engine::find_block_cipher);
+ }
+
+/*************************************************
+* Acquire a StreamCipher *
+*************************************************/
+const StreamCipher* Engine::stream_cipher(const std::string& name) const
+ {
+ return lookup_algo(cache_of_sc, global_state().deref_alias(name),
+ this, &Engine::find_stream_cipher);
+ }
+
+/*************************************************
+* Acquire a HashFunction *
+*************************************************/
+const HashFunction* Engine::hash(const std::string& name) const
+ {
+ return lookup_algo(cache_of_hf, global_state().deref_alias(name),
+ this, &Engine::find_hash);
+ }
+
+/*************************************************
+* Acquire a MessageAuthenticationCode *
+*************************************************/
+const MessageAuthenticationCode* Engine::mac(const std::string& name) const
+ {
+ return lookup_algo(cache_of_mac, global_state().deref_alias(name),
+ this, &Engine::find_mac);
+ }
+
+/*************************************************
+* Acquire a S2K object *
+*************************************************/
+const S2K* Engine::s2k(const std::string& name) const
+ {
+ return lookup_algo(cache_of_s2k, global_state().deref_alias(name),
+ this, &Engine::find_s2k);
+ }
+
+/*************************************************
+* Acquire a cipher padding object *
+*************************************************/
+const BlockCipherModePaddingMethod*
+Engine::bc_pad(const std::string& name) const
+ {
+ return lookup_algo(cache_of_bc_pad, global_state().deref_alias(name),
+ this, &Engine::find_bc_pad);
+ }
+
+/*************************************************
+* Add a block cipher to the lookup table *
+*************************************************/
+void Engine::add_algorithm(BlockCipher* algo) const
+ {
+ cache_of_bc->add(algo);
+ }
+
+/*************************************************
+* Add a stream cipher to the lookup table *
+*************************************************/
+void Engine::add_algorithm(StreamCipher* algo) const
+ {
+ cache_of_sc->add(algo);
+ }
+
+/*************************************************
+* Add a hash function to the lookup table *
+*************************************************/
+void Engine::add_algorithm(HashFunction* algo) const
+ {
+ cache_of_hf->add(algo);
+ }
+
+/*************************************************
+* Add a MAC to the lookup table *
+*************************************************/
+void Engine::add_algorithm(MessageAuthenticationCode* algo) const
+ {
+ cache_of_mac->add(algo);
+ }
+
+/*************************************************
+* Add a S2K to the lookup table *
+*************************************************/
+void Engine::add_algorithm(S2K* algo) const
+ {
+ cache_of_s2k->add(algo);
+ }
+
+/*************************************************
+* Add a cipher pad method to the lookup table *
+*************************************************/
+void Engine::add_algorithm(BlockCipherModePaddingMethod* algo) const
+ {
+ cache_of_bc_pad->add(algo);
+ }
+
+/*************************************************
+* Create an Engine *
+*************************************************/
+Engine::Engine()
+ {
+ cache_of_bc = new Algorithm_Cache_Impl<BlockCipher>();
+ cache_of_sc = new Algorithm_Cache_Impl<StreamCipher>();
+ cache_of_hf = new Algorithm_Cache_Impl<HashFunction>();
+ cache_of_mac = new Algorithm_Cache_Impl<MessageAuthenticationCode>();
+ cache_of_s2k = new Algorithm_Cache_Impl<S2K>();
+ cache_of_bc_pad =
+ new Algorithm_Cache_Impl<BlockCipherModePaddingMethod>();
+ }
+
+/*************************************************
+* Destroy an Engine *
+*************************************************/
+Engine::~Engine()
+ {
+ delete cache_of_bc;
+ delete cache_of_sc;
+ delete cache_of_hf;
+ delete cache_of_mac;
+ delete cache_of_s2k;
+ delete cache_of_bc_pad;
+ }
+
+/*************************************************
+* Basic No-Op Engine Implementation *
+*************************************************/
+BlockCipher* Engine::find_block_cipher(const std::string&) const
+ {
+ return 0;
+ }
+
+/*************************************************
+* Basic No-Op Engine Implementation *
+*************************************************/
+StreamCipher* Engine::find_stream_cipher(const std::string&) const
+ {
+ return 0;
+ }
+
+/*************************************************
+* Basic No-Op Engine Implementation *
+*************************************************/
+HashFunction* Engine::find_hash(const std::string&) const
+ {
+ return 0;
+ }
+
+/*************************************************
+* Basic No-Op Engine Implementation *
+*************************************************/
+MessageAuthenticationCode* Engine::find_mac(const std::string&) const
+ {
+ return 0;
+ }
+
+/*************************************************
+* Basic No-Op Engine Implementation *
+*************************************************/
+S2K* Engine::find_s2k(const std::string&) const
+ {
+ return 0;
+ }
+
+/*************************************************
+* Basic No-Op Engine Implementation *
+*************************************************/
+BlockCipherModePaddingMethod* Engine::find_bc_pad(const std::string&) const
+ {
+ return 0;
+ }
+
+/*************************************************
+* Basic No-Op Engine Implementation *
+*************************************************/
+Keyed_Filter* Engine::get_cipher(const std::string&, Cipher_Dir)
+ {
+ return 0;
+ }
+
+}
diff --git a/src/core/eng_def.h b/src/core/eng_def.h
new file mode 100644
index 000000000..95f1fc0f7
--- /dev/null
+++ b/src/core/eng_def.h
@@ -0,0 +1,46 @@
+/*************************************************
+* Default Engine Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_DEFAULT_ENGINE_H__
+#define BOTAN_DEFAULT_ENGINE_H__
+
+#include <botan/engine.h>
+
+namespace Botan {
+
+/*************************************************
+* Default Engine *
+*************************************************/
+class BOTAN_DLL Default_Engine : public Engine
+ {
+ public:
+ IF_Operation* if_op(const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&) const;
+ DSA_Operation* dsa_op(const DL_Group&, const BigInt&,
+ const BigInt&) const;
+ NR_Operation* nr_op(const DL_Group&, const BigInt&, const BigInt&) const;
+ ELG_Operation* elg_op(const DL_Group&, const BigInt&,
+ const BigInt&) const;
+ DH_Operation* dh_op(const DL_Group&, const BigInt&) const;
+
+ Modular_Exponentiator* mod_exp(const BigInt&,
+ Power_Mod::Usage_Hints) const;
+
+ Keyed_Filter* get_cipher(const std::string&, Cipher_Dir);
+ private:
+ BlockCipher* find_block_cipher(const std::string&) const;
+ StreamCipher* find_stream_cipher(const std::string&) const;
+ HashFunction* find_hash(const std::string&) const;
+ MessageAuthenticationCode* find_mac(const std::string&) const;
+
+ class S2K* find_s2k(const std::string&) const;
+ class BlockCipherModePaddingMethod*
+ find_bc_pad(const std::string&) const;
+ };
+
+}
+
+#endif
diff --git a/src/core/engine.cpp b/src/core/engine.cpp
new file mode 100644
index 000000000..8511c07c2
--- /dev/null
+++ b/src/core/engine.cpp
@@ -0,0 +1,370 @@
+/*************************************************
+* Engine Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/engine.h>
+#include <botan/libstate.h>
+#include <botan/lookup.h>
+#include <botan/look_add.h>
+#include <botan/eng_def.h>
+
+namespace Botan {
+
+namespace Engine_Core {
+
+/*************************************************
+* Acquire an IF op *
+*************************************************/
+IF_Operation* if_op(const BigInt& e, const BigInt& n, const BigInt& d,
+ const BigInt& p, const BigInt& q, const BigInt& d1,
+ const BigInt& d2, const BigInt& c)
+ {
+ Library_State::Engine_Iterator i(global_state());
+
+ while(const Engine* engine = i.next())
+ {
+ IF_Operation* op = engine->if_op(e, n, d, p, q, d1, d2, c);
+ if(op)
+ return op;
+ }
+
+ throw Lookup_Error("Engine_Core::if_op: Unable to find a working engine");
+ }
+
+/*************************************************
+* Acquire a DSA op *
+*************************************************/
+DSA_Operation* dsa_op(const DL_Group& group, const BigInt& y, const BigInt& x)
+ {
+ Library_State::Engine_Iterator i(global_state());
+
+ while(const Engine* engine = i.next())
+ {
+ DSA_Operation* op = engine->dsa_op(group, y, x);
+ if(op)
+ return op;
+ }
+
+ throw Lookup_Error("Engine_Core::dsa_op: Unable to find a working engine");
+ }
+
+/*************************************************
+* Acquire a NR op *
+*************************************************/
+NR_Operation* nr_op(const DL_Group& group, const BigInt& y, const BigInt& x)
+ {
+ Library_State::Engine_Iterator i(global_state());
+
+ while(const Engine* engine = i.next())
+ {
+ NR_Operation* op = engine->nr_op(group, y, x);
+ if(op)
+ return op;
+ }
+
+ throw Lookup_Error("Engine_Core::nr_op: Unable to find a working engine");
+ }
+
+/*************************************************
+* Acquire an ElGamal op *
+*************************************************/
+ELG_Operation* elg_op(const DL_Group& group, const BigInt& y, const BigInt& x)
+ {
+ Library_State::Engine_Iterator i(global_state());
+
+ while(const Engine* engine = i.next())
+ {
+ ELG_Operation* op = engine->elg_op(group, y, x);
+ if(op)
+ return op;
+ }
+
+ throw Lookup_Error("Engine_Core::elg_op: Unable to find a working engine");
+ }
+
+/*************************************************
+* Acquire a DH op *
+*************************************************/
+DH_Operation* dh_op(const DL_Group& group, const BigInt& x)
+ {
+ Library_State::Engine_Iterator i(global_state());
+
+ while(const Engine* engine = i.next())
+ {
+ DH_Operation* op = engine->dh_op(group, x);
+ if(op)
+ return op;
+ }
+
+ throw Lookup_Error("Engine_Core::dh_op: Unable to find a working engine");
+ }
+
+/*************************************************
+* Acquire a modular exponentiator *
+*************************************************/
+Modular_Exponentiator* mod_exp(const BigInt& n, Power_Mod::Usage_Hints hints)
+ {
+ Library_State::Engine_Iterator i(global_state());
+
+ while(const Engine* engine = i.next())
+ {
+ Modular_Exponentiator* op = engine->mod_exp(n, hints);
+
+ if(op)
+ return op;
+ }
+
+ throw Lookup_Error("Engine_Core::mod_exp: Unable to find a working engine");
+ }
+
+}
+
+/*************************************************
+* Acquire a block cipher *
+*************************************************/
+const BlockCipher* retrieve_block_cipher(const std::string& name)
+ {
+ Library_State::Engine_Iterator i(global_state());
+
+ while(const Engine* engine = i.next())
+ {
+ const BlockCipher* algo = engine->block_cipher(name);
+ if(algo)
+ return algo;
+ }
+
+ return 0;
+ }
+
+/*************************************************
+* Acquire a stream cipher *
+*************************************************/
+const StreamCipher* retrieve_stream_cipher(const std::string& name)
+ {
+ Library_State::Engine_Iterator i(global_state());
+
+ while(const Engine* engine = i.next())
+ {
+ const StreamCipher* algo = engine->stream_cipher(name);
+ if(algo)
+ return algo;
+ }
+
+ return 0;
+ }
+
+/*************************************************
+* Acquire a hash function *
+*************************************************/
+const HashFunction* retrieve_hash(const std::string& name)
+ {
+ Library_State::Engine_Iterator i(global_state());
+
+ while(const Engine* engine = i.next())
+ {
+ const HashFunction* algo = engine->hash(name);
+ if(algo)
+ return algo;
+ }
+
+ return 0;
+ }
+
+/*************************************************
+* Acquire an authentication code *
+*************************************************/
+const MessageAuthenticationCode* retrieve_mac(const std::string& name)
+ {
+ Library_State::Engine_Iterator i(global_state());
+
+ while(const Engine* engine = i.next())
+ {
+ const MessageAuthenticationCode* algo = engine->mac(name);
+ if(algo)
+ return algo;
+ }
+
+ return 0;
+ }
+
+/*************************************************
+* Acquire a string-to-key algorithm *
+*************************************************/
+const S2K* retrieve_s2k(const std::string& name)
+ {
+ Library_State::Engine_Iterator i(global_state());
+
+ while(const Engine* engine = i.next())
+ {
+ const S2K* algo = engine->s2k(name);
+ if(algo)
+ return algo;
+ }
+
+ return 0;
+ }
+
+/*************************************************
+* Retrieve a block cipher padding method *
+*************************************************/
+const BlockCipherModePaddingMethod* retrieve_bc_pad(const std::string& name)
+ {
+ Library_State::Engine_Iterator i(global_state());
+
+ while(const Engine* engine = i.next())
+ {
+ const BlockCipherModePaddingMethod* algo = engine->bc_pad(name);
+ if(algo)
+ return algo;
+ }
+
+ return 0;
+ }
+
+/*************************************************
+* Add a new block cipher *
+*************************************************/
+void add_algorithm(BlockCipher* algo)
+ {
+ Library_State::Engine_Iterator i(global_state());
+
+ while(Engine* engine_base = i.next())
+ {
+ Default_Engine* engine = dynamic_cast<Default_Engine*>(engine_base);
+ if(engine)
+ {
+ engine->add_algorithm(algo);
+ return;
+ }
+ }
+
+ throw Invalid_State("add_algorithm: Couldn't find the Default_Engine");
+ }
+
+/*************************************************
+* Add a new stream cipher *
+*************************************************/
+void add_algorithm(StreamCipher* algo)
+ {
+ Library_State::Engine_Iterator i(global_state());
+
+ while(Engine* engine_base = i.next())
+ {
+ Default_Engine* engine = dynamic_cast<Default_Engine*>(engine_base);
+ if(engine)
+ {
+ engine->add_algorithm(algo);
+ return;
+ }
+ }
+
+ throw Invalid_State("add_algorithm: Couldn't find the Default_Engine");
+ }
+
+/*************************************************
+* Add a new hash function *
+*************************************************/
+void add_algorithm(HashFunction* algo)
+ {
+ Library_State::Engine_Iterator i(global_state());
+
+ while(Engine* engine_base = i.next())
+ {
+ Default_Engine* engine = dynamic_cast<Default_Engine*>(engine_base);
+ if(engine)
+ {
+ engine->add_algorithm(algo);
+ return;
+ }
+ }
+
+ throw Invalid_State("add_algorithm: Couldn't find the Default_Engine");
+ }
+
+/*************************************************
+* Add a new authentication code *
+*************************************************/
+void add_algorithm(MessageAuthenticationCode* algo)
+ {
+ Library_State::Engine_Iterator i(global_state());
+
+ while(Engine* engine_base = i.next())
+ {
+ Default_Engine* engine = dynamic_cast<Default_Engine*>(engine_base);
+ if(engine)
+ {
+ engine->add_algorithm(algo);
+ return;
+ }
+ }
+
+ throw Invalid_State("add_algorithm: Couldn't find the Default_Engine");
+ }
+
+/*************************************************
+* Add a padding method to the lookup table *
+*************************************************/
+void add_algorithm(BlockCipherModePaddingMethod* algo)
+ {
+ Library_State::Engine_Iterator i(global_state());
+
+ while(Engine* engine_base = i.next())
+ {
+ Default_Engine* engine = dynamic_cast<Default_Engine*>(engine_base);
+ if(engine)
+ {
+ engine->add_algorithm(algo);
+ return;
+ }
+ }
+
+ throw Invalid_State("add_algorithm: Couldn't find the Default_Engine");
+ }
+
+/*************************************************
+* Get a cipher object *
+*************************************************/
+Keyed_Filter* get_cipher(const std::string& algo_spec,
+ Cipher_Dir direction)
+ {
+ Library_State::Engine_Iterator i(global_state());
+
+ while(Engine* engine = i.next())
+ {
+ Keyed_Filter* algo = engine->get_cipher(algo_spec, direction);
+ if(algo)
+ return algo;
+ }
+
+ throw Algorithm_Not_Found(algo_spec);
+ }
+
+/*************************************************
+* Get a cipher object *
+*************************************************/
+Keyed_Filter* get_cipher(const std::string& algo_spec,
+ const SymmetricKey& key,
+ const InitializationVector& iv,
+ Cipher_Dir direction)
+ {
+ Keyed_Filter* cipher = get_cipher(algo_spec, direction);
+ cipher->set_key(key);
+
+ if(iv.length())
+ cipher->set_iv(iv);
+
+ return cipher;
+ }
+
+/*************************************************
+* Get a cipher object *
+*************************************************/
+Keyed_Filter* get_cipher(const std::string& algo_spec,
+ const SymmetricKey& key,
+ Cipher_Dir direction)
+ {
+ return get_cipher(algo_spec, key, InitializationVector(), direction);
+ }
+
+}
diff --git a/src/core/engine.h b/src/core/engine.h
new file mode 100644
index 000000000..13007e662
--- /dev/null
+++ b/src/core/engine.h
@@ -0,0 +1,123 @@
+/*************************************************
+* Engine Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_ENGINE_H__
+#define BOTAN_ENGINE_H__
+
+#include <botan/base.h>
+#include <botan/mutex.h>
+#include <botan/pk_ops.h>
+#include <botan/pow_mod.h>
+#include <botan/basefilt.h>
+#include <botan/enums.h>
+#include <utility>
+#include <map>
+
+namespace Botan {
+
+/*************************************************
+* Engine Base Class *
+*************************************************/
+class BOTAN_DLL Engine
+ {
+ public:
+ template<typename T>
+ class BOTAN_DLL Algorithm_Cache
+ {
+ public:
+ virtual T* get(const std::string&) const = 0;
+ virtual void add(T* algo, const std::string& = "") const = 0;
+ virtual ~Algorithm_Cache() {}
+ };
+
+ virtual IF_Operation* if_op(const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&) const;
+ virtual DSA_Operation* dsa_op(const DL_Group&, const BigInt&,
+ const BigInt&) const;
+ virtual NR_Operation* nr_op(const DL_Group&, const BigInt&,
+ const BigInt&) const;
+ virtual ELG_Operation* elg_op(const DL_Group&, const BigInt&,
+ const BigInt&) const;
+ virtual DH_Operation* dh_op(const DL_Group&, const BigInt&) const;
+
+ virtual Modular_Exponentiator* mod_exp(const BigInt&,
+ Power_Mod::Usage_Hints) const;
+
+ virtual Keyed_Filter* get_cipher(const std::string&, Cipher_Dir);
+
+ const BlockCipher* block_cipher(const std::string&) const;
+ const StreamCipher* stream_cipher(const std::string&) const;
+ const HashFunction* hash(const std::string&) const;
+ const MessageAuthenticationCode* mac(const std::string&) const;
+ const class S2K* s2k(const std::string&) const;
+ const class BlockCipherModePaddingMethod*
+ bc_pad(const std::string&) const;
+
+ void add_algorithm(BlockCipher*) const;
+ void add_algorithm(StreamCipher*) const;
+ void add_algorithm(HashFunction*) const;
+ void add_algorithm(MessageAuthenticationCode*) const;
+ void add_algorithm(class S2K*) const;
+ void add_algorithm(class BlockCipherModePaddingMethod*) const;
+
+ Engine();
+ virtual ~Engine();
+ private:
+ virtual BlockCipher* find_block_cipher(const std::string&) const;
+ virtual StreamCipher* find_stream_cipher(const std::string&) const;
+ virtual HashFunction* find_hash(const std::string&) const;
+ virtual MessageAuthenticationCode* find_mac(const std::string&) const;
+ virtual class S2K* find_s2k(const std::string&) const;
+ virtual class BlockCipherModePaddingMethod*
+ find_bc_pad(const std::string&) const;
+
+ template<typename T>
+ const T* lookup_algo(const Algorithm_Cache<T>* cache,
+ const std::string& name,
+ const Engine* engine,
+ T* (Engine::*find)(const std::string&) const) const
+ {
+ T* algo = cache->get(name);
+ if(!algo)
+ {
+ algo = (engine->*find)(name);
+ if(algo)
+ cache->add(algo, name);
+ }
+ return algo;
+ }
+
+ Algorithm_Cache<BlockCipher>* cache_of_bc;
+ Algorithm_Cache<StreamCipher>* cache_of_sc;
+ Algorithm_Cache<HashFunction>* cache_of_hf;
+ Algorithm_Cache<MessageAuthenticationCode>* cache_of_mac;
+ Algorithm_Cache<BlockCipherModePaddingMethod>* cache_of_bc_pad;
+ Algorithm_Cache<S2K>* cache_of_s2k;
+ };
+
+namespace Engine_Core {
+
+/*************************************************
+* Get an operation from an Engine *
+*************************************************/
+Modular_Exponentiator* mod_exp(const BigInt&, Power_Mod::Usage_Hints);
+
+IF_Operation* if_op(const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&);
+
+DSA_Operation* dsa_op(const DL_Group&, const BigInt&, const BigInt&);
+NR_Operation* nr_op(const DL_Group&, const BigInt&, const BigInt&);
+
+ELG_Operation* elg_op(const DL_Group&, const BigInt&, const BigInt&);
+
+DH_Operation* dh_op(const DL_Group&, const BigInt&);
+
+}
+
+}
+
+#endif
diff --git a/src/core/enums.h b/src/core/enums.h
new file mode 100644
index 000000000..dc404b728
--- /dev/null
+++ b/src/core/enums.h
@@ -0,0 +1,67 @@
+/*************************************************
+* Enumerations Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_ENUMS_H__
+#define BOTAN_ENUMS_H__
+
+namespace Botan {
+
+/*************************************************
+* X.509v3 Key Constraints *
+*************************************************/
+enum Key_Constraints {
+ NO_CONSTRAINTS = 0,
+ DIGITAL_SIGNATURE = 32768,
+ NON_REPUDIATION = 16384,
+ KEY_ENCIPHERMENT = 8192,
+ DATA_ENCIPHERMENT = 4096,
+ KEY_AGREEMENT = 2048,
+ KEY_CERT_SIGN = 1024,
+ CRL_SIGN = 512,
+ ENCIPHER_ONLY = 256,
+ DECIPHER_ONLY = 128
+};
+
+/*************************************************
+* X.509v2 CRL Reason Code *
+*************************************************/
+enum CRL_Code {
+ UNSPECIFIED = 0,
+ KEY_COMPROMISE = 1,
+ CA_COMPROMISE = 2,
+ AFFILIATION_CHANGED = 3,
+ SUPERSEDED = 4,
+ CESSATION_OF_OPERATION = 5,
+ CERTIFICATE_HOLD = 6,
+ REMOVE_FROM_CRL = 8,
+ PRIVLEDGE_WITHDRAWN = 9,
+ AA_COMPROMISE = 10,
+
+ DELETE_CRL_ENTRY = 0xFF00,
+ OCSP_GOOD = 0xFF01,
+ OCSP_UNKNOWN = 0xFF02
+};
+
+/*************************************************
+* Various Other Enumerations *
+*************************************************/
+enum Decoder_Checking { NONE, IGNORE_WS, FULL_CHECK };
+
+enum X509_Encoding { RAW_BER, PEM };
+
+enum Cipher_Dir { ENCRYPTION, DECRYPTION };
+
+enum Character_Set {
+ LOCAL_CHARSET,
+ UCS2_CHARSET,
+ UTF8_CHARSET,
+ LATIN1_CHARSET
+};
+
+static const u32bit NO_CERT_PATH_LIMIT = 0xFFFFFFF0;
+
+}
+
+#endif
diff --git a/src/core/exceptn.cpp b/src/core/exceptn.cpp
new file mode 100644
index 000000000..29357afa5
--- /dev/null
+++ b/src/core/exceptn.cpp
@@ -0,0 +1,60 @@
+/*************************************************
+* Exceptions Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/exceptn.h>
+#include <botan/parsing.h>
+
+namespace Botan {
+
+/*************************************************
+* Constructor for Invalid_Key_Length *
+*************************************************/
+Invalid_Key_Length::Invalid_Key_Length(const std::string& name, u32bit length)
+ {
+ set_msg(name + " cannot accept a key of length " + to_string(length));
+ }
+
+/*************************************************
+* Constructor for Invalid_Block_Size *
+*************************************************/
+Invalid_Block_Size::Invalid_Block_Size(const std::string& mode,
+ const std::string& pad)
+ {
+ set_msg("Padding method " + pad + " cannot be used with " + mode);
+ }
+
+/*************************************************
+* Constructor for Invalid_IV_Length *
+*************************************************/
+Invalid_IV_Length::Invalid_IV_Length(const std::string& mode, u32bit bad_len)
+ {
+ set_msg("IV length " + to_string(bad_len) + " is invalid for " + mode);
+ }
+
+/*************************************************
+* Constructor for Algorithm_Not_Found *
+*************************************************/
+Algorithm_Not_Found::Algorithm_Not_Found(const std::string& name)
+ {
+ set_msg("Could not find any algorithm named \"" + name + "\"");
+ }
+
+/*************************************************
+* Constructor for Invalid_Algorithm_Name *
+*************************************************/
+Invalid_Algorithm_Name::Invalid_Algorithm_Name(const std::string& name)
+ {
+ set_msg("Invalid algorithm name: " + name);
+ }
+
+/*************************************************
+* Constructor for Config_Error *
+*************************************************/
+Config_Error::Config_Error(const std::string& err, u32bit line)
+ {
+ set_msg("Config error at line " + to_string(line) + ": " + err);
+ }
+
+}
diff --git a/src/core/exceptn.h b/src/core/exceptn.h
new file mode 100644
index 000000000..3bfec2fd2
--- /dev/null
+++ b/src/core/exceptn.h
@@ -0,0 +1,195 @@
+/*************************************************
+* Exceptions Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_EXCEPTION_H__
+#define BOTAN_EXCEPTION_H__
+
+#include <botan/types.h>
+#include <exception>
+#include <string>
+
+namespace Botan {
+
+/*************************************************
+* Exception Base Class *
+*************************************************/
+class BOTAN_DLL Exception : public std::exception
+ {
+ public:
+ const char* what() const throw() { return msg.c_str(); }
+ Exception(const std::string& m = "Unknown error") { set_msg(m); }
+ virtual ~Exception() throw() {}
+ protected:
+ void set_msg(const std::string& m) { msg = "Botan: " + m; }
+ private:
+ std::string msg;
+ };
+
+/*************************************************
+* Invalid_Argument Exception *
+*************************************************/
+struct BOTAN_DLL Invalid_Argument : public Exception
+ {
+ Invalid_Argument(const std::string& err = "") : Exception(err) {}
+ };
+
+/*************************************************
+* Invalid_Key_Length Exception *
+*************************************************/
+struct BOTAN_DLL Invalid_Key_Length : public Invalid_Argument
+ {
+ Invalid_Key_Length(const std::string&, u32bit);
+ };
+
+/*************************************************
+* Invalid_Block_Size Exception *
+*************************************************/
+struct BOTAN_DLL Invalid_Block_Size : public Invalid_Argument
+ {
+ Invalid_Block_Size(const std::string&, const std::string&);
+ };
+
+/*************************************************
+* Invalid_IV_Length Exception *
+*************************************************/
+struct BOTAN_DLL Invalid_IV_Length : public Invalid_Argument
+ {
+ Invalid_IV_Length(const std::string&, u32bit);
+ };
+
+/*************************************************
+* Invalid_State Exception *
+*************************************************/
+struct BOTAN_DLL Invalid_State : public Exception
+ {
+ Invalid_State(const std::string& err) : Exception(err) {}
+ };
+
+/*************************************************
+* PRNG_Unseeded Exception *
+*************************************************/
+struct BOTAN_DLL PRNG_Unseeded : public Invalid_State
+ {
+ PRNG_Unseeded(const std::string& algo) :
+ Invalid_State("PRNG not seeded: " + algo) {}
+ };
+
+/*************************************************
+* Policy_Violation Exception *
+*************************************************/
+struct BOTAN_DLL Policy_Violation : public Invalid_State
+ {
+ Policy_Violation(const std::string& err) :
+ Invalid_State("Policy violation: " + err) {}
+ };
+
+/*************************************************
+* Lookup_Error Exception *
+*************************************************/
+struct BOTAN_DLL Lookup_Error : public Exception
+ {
+ Lookup_Error(const std::string& err) : Exception(err) {}
+ };
+
+/*************************************************
+* Algorithm_Not_Found Exception *
+*************************************************/
+struct BOTAN_DLL Algorithm_Not_Found : public Exception
+ {
+ Algorithm_Not_Found(const std::string&);
+ };
+
+/*************************************************
+* Format_Error Exception *
+*************************************************/
+struct BOTAN_DLL Format_Error : public Exception
+ {
+ Format_Error(const std::string& err = "") : Exception(err) {}
+ };
+
+/*************************************************
+* Invalid_Algorithm_Name Exception *
+*************************************************/
+struct BOTAN_DLL Invalid_Algorithm_Name : public Format_Error
+ {
+ Invalid_Algorithm_Name(const std::string&);
+ };
+
+/*************************************************
+* Encoding_Error Exception *
+*************************************************/
+struct BOTAN_DLL Encoding_Error : public Format_Error
+ {
+ Encoding_Error(const std::string& name) :
+ Format_Error("Encoding error: " + name) {}
+ };
+
+/*************************************************
+* Decoding_Error Exception *
+*************************************************/
+struct BOTAN_DLL Decoding_Error : public Format_Error
+ {
+ Decoding_Error(const std::string& name) :
+ Format_Error("Decoding error: " + name) {}
+ };
+
+/*************************************************
+* Invalid_OID Exception *
+*************************************************/
+struct BOTAN_DLL Invalid_OID : public Decoding_Error
+ {
+ Invalid_OID(const std::string& oid) :
+ Decoding_Error("Invalid ASN.1 OID: " + oid) {}
+ };
+
+/*************************************************
+* Stream_IO_Error Exception *
+*************************************************/
+struct BOTAN_DLL Stream_IO_Error : public Exception
+ {
+ Stream_IO_Error(const std::string& err) :
+ Exception("I/O error: " + err) {}
+ };
+
+/*************************************************
+* Configuration Error Exception *
+*************************************************/
+struct BOTAN_DLL Config_Error : public Format_Error
+ {
+ Config_Error(const std::string& err) :
+ Format_Error("Config error: " + err) {}
+ Config_Error(const std::string&, u32bit);
+ };
+
+/*************************************************
+* Integrity Failure Exception *
+*************************************************/
+struct BOTAN_DLL Integrity_Failure : public Exception
+ {
+ Integrity_Failure(const std::string& err) :
+ Exception("Integrity failure: " + err) {}
+ };
+
+/*************************************************
+* Internal_Error Exception *
+*************************************************/
+struct BOTAN_DLL Internal_Error : public Exception
+ {
+ Internal_Error(const std::string& err) :
+ Exception("Internal error: " + err) {}
+ };
+
+/*************************************************
+* Self Test Failure Exception *
+*************************************************/
+struct BOTAN_DLL Self_Test_Failure : public Internal_Error
+ {
+ Self_Test_Failure(const std::string& err) :
+ Internal_Error("Self test failed: " + err) {}
+ };
+
+}
+
+#endif
diff --git a/src/core/get_algo.cpp b/src/core/get_algo.cpp
new file mode 100644
index 000000000..2325c144d
--- /dev/null
+++ b/src/core/get_algo.cpp
@@ -0,0 +1,236 @@
+/*************************************************
+* Algorithm Retrieval Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/lookup.h>
+
+namespace Botan {
+
+/*************************************************
+* Get a block cipher by name *
+*************************************************/
+BlockCipher* get_block_cipher(const std::string& name)
+ {
+ const BlockCipher* cipher = retrieve_block_cipher(name);
+ if(cipher)
+ return cipher->clone();
+ throw Algorithm_Not_Found(name);
+ }
+
+/*************************************************
+* Get a stream cipher by name *
+*************************************************/
+StreamCipher* get_stream_cipher(const std::string& name)
+ {
+ const StreamCipher* cipher = retrieve_stream_cipher(name);
+ if(cipher)
+ return cipher->clone();
+ throw Algorithm_Not_Found(name);
+ }
+
+/*************************************************
+* Get a hash function by name *
+*************************************************/
+HashFunction* get_hash(const std::string& name)
+ {
+ const HashFunction* hash = retrieve_hash(name);
+ if(hash)
+ return hash->clone();
+ throw Algorithm_Not_Found(name);
+ }
+
+/*************************************************
+* Get a MAC by name *
+*************************************************/
+MessageAuthenticationCode* get_mac(const std::string& name)
+ {
+ const MessageAuthenticationCode* mac = retrieve_mac(name);
+ if(mac)
+ return mac->clone();
+ throw Algorithm_Not_Found(name);
+ }
+
+/*************************************************
+* Get a S2K algorithm by name *
+*************************************************/
+S2K* get_s2k(const std::string& name)
+ {
+ const S2K* s2k = retrieve_s2k(name);
+ if(s2k)
+ return s2k->clone();
+ throw Algorithm_Not_Found(name);
+ }
+
+/*************************************************
+* Get a block cipher padding method by name *
+*************************************************/
+const BlockCipherModePaddingMethod* get_bc_pad(const std::string& name)
+ {
+ const BlockCipherModePaddingMethod* pad = retrieve_bc_pad(name);
+ if(pad)
+ return pad;
+ throw Algorithm_Not_Found(name);
+ }
+
+/*************************************************
+* Query if an algorithm exists *
+*************************************************/
+bool have_algorithm(const std::string& name)
+ {
+ if(retrieve_block_cipher(name))
+ return true;
+ if(retrieve_stream_cipher(name))
+ return true;
+ if(retrieve_hash(name))
+ return true;
+ if(retrieve_mac(name))
+ return true;
+ return false;
+ }
+
+/*************************************************
+* Query if Botan has the named block cipher *
+*************************************************/
+bool have_block_cipher(const std::string& name)
+ {
+ return (retrieve_block_cipher(name) != 0);
+ }
+
+/*************************************************
+* Query if Botan has the named stream cipher *
+*************************************************/
+bool have_stream_cipher(const std::string& name)
+ {
+ return (retrieve_stream_cipher(name) != 0);
+ }
+
+/*************************************************
+* Query if Botan has the named hash function *
+*************************************************/
+bool have_hash(const std::string& name)
+ {
+ return (retrieve_hash(name) != 0);
+ }
+
+/*************************************************
+* Query if Botan has the named MAC *
+*************************************************/
+bool have_mac(const std::string& name)
+ {
+ return (retrieve_mac(name) != 0);
+ }
+
+/*************************************************
+* Query the block size of a cipher or hash *
+*************************************************/
+u32bit block_size_of(const std::string& name)
+ {
+ const BlockCipher* cipher = retrieve_block_cipher(name);
+ if(cipher)
+ return cipher->BLOCK_SIZE;
+
+ const HashFunction* hash = retrieve_hash(name);
+ if(hash)
+ return hash->HASH_BLOCK_SIZE;
+
+ throw Algorithm_Not_Found(name);
+ }
+
+/*************************************************
+* Query the OUTPUT_LENGTH of a hash or MAC *
+*************************************************/
+u32bit output_length_of(const std::string& name)
+ {
+ const HashFunction* hash = retrieve_hash(name);
+ if(hash)
+ return hash->OUTPUT_LENGTH;
+
+ const MessageAuthenticationCode* mac = retrieve_mac(name);
+ if(mac)
+ return mac->OUTPUT_LENGTH;
+
+ throw Algorithm_Not_Found(name);
+ }
+
+/*************************************************
+* Check if a keylength is valid for this algo *
+*************************************************/
+bool valid_keylength_for(u32bit key_len, const std::string& name)
+ {
+ const BlockCipher* bc = retrieve_block_cipher(name);
+ if(bc)
+ return bc->valid_keylength(key_len);
+
+ const StreamCipher* sc = retrieve_stream_cipher(name);
+ if(sc)
+ return sc->valid_keylength(key_len);
+
+ const MessageAuthenticationCode* mac = retrieve_mac(name);
+ if(mac)
+ return mac->valid_keylength(key_len);
+
+ throw Algorithm_Not_Found(name);
+ }
+
+/*************************************************
+* Query the MINIMUM_KEYLENGTH of an algorithm *
+*************************************************/
+u32bit min_keylength_of(const std::string& name)
+ {
+ const BlockCipher* bc = retrieve_block_cipher(name);
+ if(bc)
+ return bc->MINIMUM_KEYLENGTH;
+
+ const StreamCipher* sc = retrieve_stream_cipher(name);
+ if(sc)
+ return sc->MINIMUM_KEYLENGTH;
+
+ const MessageAuthenticationCode* mac = retrieve_mac(name);
+ if(mac)
+ return mac->MINIMUM_KEYLENGTH;
+
+ throw Algorithm_Not_Found(name);
+ }
+
+/*************************************************
+* Query the MAXIMUM_KEYLENGTH of an algorithm *
+*************************************************/
+u32bit max_keylength_of(const std::string& name)
+ {
+ const BlockCipher* bc = retrieve_block_cipher(name);
+ if(bc)
+ return bc->MAXIMUM_KEYLENGTH;
+
+ const StreamCipher* sc = retrieve_stream_cipher(name);
+ if(sc)
+ return sc->MAXIMUM_KEYLENGTH;
+
+ const MessageAuthenticationCode* mac = retrieve_mac(name);
+ if(mac)
+ return mac->MAXIMUM_KEYLENGTH;
+
+ throw Algorithm_Not_Found(name);
+ }
+
+/*************************************************
+* Query the KEYLENGTH_MULTIPLE of an algorithm *
+*************************************************/
+u32bit keylength_multiple_of(const std::string& name)
+ {
+ const BlockCipher* bc = retrieve_block_cipher(name);
+ if(bc)
+ return bc->KEYLENGTH_MULTIPLE;
+
+ const StreamCipher* sc = retrieve_stream_cipher(name);
+ if(sc)
+ return sc->KEYLENGTH_MULTIPLE;
+
+ const MessageAuthenticationCode* mac = retrieve_mac(name);
+ if(mac)
+ return mac->KEYLENGTH_MULTIPLE;
+
+ throw Algorithm_Not_Found(name);
+ }
+
+}
diff --git a/src/core/get_enc.cpp b/src/core/get_enc.cpp
new file mode 100644
index 000000000..fb5952a3e
--- /dev/null
+++ b/src/core/get_enc.cpp
@@ -0,0 +1,219 @@
+/*************************************************
+* EMSA/EME/KDF/MGF Retrieval Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/lookup.h>
+#include <botan/libstate.h>
+#include <botan/parsing.h>
+#include <botan/util.h>
+
+#if defined(BOTAN_HAS_MGF1)
+ #include <botan/mgf1.h>
+#endif
+
+#if defined(BOTAN_HAS_EMSA1)
+ #include <botan/emsa1.h>
+#endif
+
+#if defined(BOTAN_HAS_EMSA2)
+ #include <botan/emsa2.h>
+#endif
+
+#if defined(BOTAN_HAS_EMSA3)
+ #include <botan/emsa3.h>
+#endif
+
+#if defined(BOTAN_HAS_EMSA4)
+ #include <botan/emsa4.h>
+#endif
+
+#if defined(BOTAN_HAS_EMSA_RAW)
+ #include <botan/emsa_raw.h>
+#endif
+
+#if defined(BOTAN_HAS_EME1)
+ #include <botan/eme1.h>
+#endif
+
+#if defined(BOTAN_HAS_EME_PKCS1v15)
+ #include <botan/eme_pkcs.h>
+#endif
+
+#if defined(BOTAN_HAS_KDF1)
+ #include <botan/kdf1.h>
+#endif
+
+#if defined(BOTAN_HAS_KDF2)
+ #include <botan/kdf2.h>
+#endif
+
+#if defined(BOTAN_HAS_X942_PRF)
+ #include <botan/prf_x942.h>
+#endif
+
+#if defined(BOTAN_HAS_SSL_V3_PRF)
+ #include <botan/prf_ssl3.h>
+#endif
+
+#if defined(BOTAN_HAS_TLS_V10_PRF)
+ #include <botan/prf_tls.h>
+#endif
+
+namespace Botan {
+
+/*************************************************
+* Get an EMSA by name *
+*************************************************/
+EMSA* get_emsa(const std::string& algo_spec)
+ {
+ std::vector<std::string> name = parse_algorithm_name(algo_spec);
+ const std::string emsa_name = global_state().deref_alias(name[0]);
+
+#if defined(BOTAN_HAS_EMSA_RAW)
+ if(emsa_name == "Raw")
+ {
+ if(name.size() == 1)
+ return new EMSA_Raw;
+ }
+#endif
+
+#if defined(BOTAN_HAS_EMSA1)
+ if(emsa_name == "EMSA1")
+ {
+ if(name.size() == 2)
+ return new EMSA1(name[1]);
+ }
+#endif
+
+#if defined(BOTAN_HAS_EMSA2)
+ if(emsa_name == "EMSA2")
+ {
+ if(name.size() == 2)
+ return new EMSA2(name[1]);
+ }
+#endif
+
+#if defined(BOTAN_HAS_EMSA3)
+ if(emsa_name == "EMSA3")
+ {
+ if(name.size() == 2)
+ return new EMSA3(name[1]);
+ }
+#endif
+
+#if defined(BOTAN_HAS_EMSA4)
+ if(emsa_name == "EMSA4")
+ {
+ if(name.size() == 2)
+ return new EMSA4(name[1], "MGF1");
+ if(name.size() == 3)
+ return new EMSA4(name[1], name[2]);
+ if(name.size() == 4)
+ return new EMSA4(name[1], name[2], to_u32bit(name[3]));
+ }
+#endif
+
+ throw Algorithm_Not_Found(algo_spec);
+ }
+
+/*************************************************
+* Get an EME by name *
+*************************************************/
+EME* get_eme(const std::string& algo_spec)
+ {
+ std::vector<std::string> name = parse_algorithm_name(algo_spec);
+ const std::string eme_name = global_state().deref_alias(name[0]);
+
+#if defined(BOTAN_HAS_EME_PKCS1v15)
+ if(eme_name == "PKCS1v15")
+ {
+ if(name.size() == 1)
+ return new EME_PKCS1v15;
+ }
+#endif
+
+#if defined(BOTAN_HAS_EME1)
+ if(eme_name == "EME1")
+ {
+ if(name.size() == 2)
+ return new EME1(name[1], "MGF1");
+ if(name.size() == 3)
+ return new EME1(name[1], name[2]);
+ }
+#endif
+
+ throw Algorithm_Not_Found(algo_spec);
+ }
+
+/*************************************************
+* Get an KDF by name *
+*************************************************/
+KDF* get_kdf(const std::string& algo_spec)
+ {
+ std::vector<std::string> name = parse_algorithm_name(algo_spec);
+ const std::string kdf_name = global_state().deref_alias(name[0]);
+
+#if defined(BOTAN_HAS_KDF1)
+ if(kdf_name == "KDF1")
+ {
+ if(name.size() == 2)
+ return new KDF1(name[1]);
+ }
+#endif
+
+#if defined(BOTAN_HAS_KDF2)
+ if(kdf_name == "KDF2")
+ {
+ if(name.size() == 2)
+ return new KDF2(name[1]);
+ }
+#endif
+
+#if defined(BOTAN_HAS_X942_PRF)
+ if(kdf_name == "X9.42-PRF")
+ {
+ if(name.size() == 2)
+ return new X942_PRF(name[1]);
+ }
+#endif
+
+#if defined(BOTAN_HAS_TLS_V10_PRF)
+ if(kdf_name == "TLS-PRF")
+ {
+ if(name.size() == 1)
+ return new TLS_PRF;
+ }
+#endif
+
+#if defined(BOTAN_HAS_SSL_V3_PRF)
+ if(kdf_name == "SSL3-PRF")
+ {
+ if(name.size() == 1)
+ return new SSL3_PRF;
+ }
+#endif
+
+ throw Algorithm_Not_Found(algo_spec);
+ }
+
+/*************************************************
+* Get a MGF by name *
+*************************************************/
+MGF* get_mgf(const std::string& algo_spec)
+ {
+ std::vector<std::string> name = parse_algorithm_name(algo_spec);
+ const std::string mgf_name = global_state().deref_alias(name[0]);
+
+#ifdef BOTAN_HAS_MGF1
+ if(mgf_name == "MGF1")
+ {
+ if(name.size() == 2)
+ return new MGF1(get_hash(name[1]));
+ }
+#endif
+
+ throw Algorithm_Not_Found(algo_spec);
+ }
+
+}
diff --git a/src/core/get_pbe.cpp b/src/core/get_pbe.cpp
new file mode 100644
index 000000000..6bd85b3e1
--- /dev/null
+++ b/src/core/get_pbe.cpp
@@ -0,0 +1,88 @@
+/*************************************************
+* PBE Retrieval Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/lookup.h>
+#include <botan/pbe.h>
+#include <botan/oids.h>
+#include <botan/parsing.h>
+
+#if defined(BOTAN_HAS_PBE_PKCS_V15)
+ #include <botan/pbes1.h>
+#endif
+
+#if defined(BOTAN_HAS_PBE_PKCS_V20)
+ #include <botan/pbes2.h>
+#endif
+
+namespace Botan {
+
+/*************************************************
+* Get an encryption PBE, set new parameters *
+*************************************************/
+PBE* get_pbe(const std::string& pbe_name)
+ {
+ std::vector<std::string> algo_name;
+ algo_name = parse_algorithm_name(pbe_name);
+
+ if(algo_name.size() != 3)
+ throw Invalid_Algorithm_Name(pbe_name);
+
+ const std::string pbe = algo_name[0];
+ const std::string digest = algo_name[1];
+ const std::string cipher = algo_name[2];
+
+ PBE* pbe_obj = 0;
+
+#if defined(BOTAN_HAS_PBE_PKCS_V15)
+ if(!pbe_obj && pbe == "PBE-PKCS5v15")
+ pbe_obj = new PBE_PKCS5v15(digest, cipher, ENCRYPTION);
+#endif
+
+#if defined(BOTAN_HAS_PBE_PKCS_V20)
+ if(!pbe_obj && pbe == "PBE-PKCS5v20")
+ pbe_obj = new PBE_PKCS5v20(digest, cipher);
+#endif
+
+ if(!pbe_obj)
+ throw Algorithm_Not_Found(pbe_name);
+
+ return pbe_obj;
+ }
+
+/*************************************************
+* Get a decryption PBE, decode parameters *
+*************************************************/
+PBE* get_pbe(const OID& pbe_oid, DataSource& params)
+ {
+ std::vector<std::string> algo_name;
+ algo_name = parse_algorithm_name(OIDS::lookup(pbe_oid));
+
+ if(algo_name.size() < 1)
+ throw Invalid_Algorithm_Name(pbe_oid.as_string());
+ const std::string pbe_algo = algo_name[0];
+
+ if(pbe_algo == "PBE-PKCS5v15")
+ {
+#if defined(BOTAN_HAS_PBE_PKCS_V15)
+ if(algo_name.size() != 3)
+ throw Invalid_Algorithm_Name(pbe_oid.as_string());
+ const std::string digest = algo_name[1];
+ const std::string cipher = algo_name[2];
+ PBE* pbe = new PBE_PKCS5v15(digest, cipher, DECRYPTION);
+ pbe->decode_params(params);
+ return pbe;
+#endif
+ }
+ else if(pbe_algo == "PBE-PKCS5v20")
+ {
+#if defined(BOTAN_HAS_PBE_PKCS_V20)
+ return new PBE_PKCS5v20(params);
+#endif
+ }
+
+ throw Algorithm_Not_Found(pbe_oid.as_string());
+ }
+
+}
diff --git a/src/core/init.h b/src/core/init.h
new file mode 100644
index 000000000..f4296a868
--- /dev/null
+++ b/src/core/init.h
@@ -0,0 +1,50 @@
+/*************************************************
+* Library Initialization Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_INIT_H__
+#define BOTAN_INIT_H__
+
+#include <botan/build.h>
+#include <string>
+#include <map>
+
+namespace Botan {
+
+/*************************************************
+* Options for initializing the library *
+*************************************************/
+class BOTAN_DLL InitializerOptions
+ {
+ public:
+ bool thread_safe() const;
+ bool use_engines() const;
+ bool secure_memory() const;
+ bool fips_mode() const;
+ bool self_test() const;
+
+ InitializerOptions(const std::string&);
+ private:
+ std::map<std::string, std::string> args;
+ };
+
+/*************************************************
+* Library Initialization/Shutdown Object *
+*************************************************/
+class BOTAN_DLL LibraryInitializer
+ {
+ public:
+ static void initialize(const std::string& = "");
+ static void initialize(const InitializerOptions&);
+ static void initialize(const InitializerOptions&, class Modules&);
+ static void deinitialize();
+
+ LibraryInitializer(const std::string& args = "") { initialize(args); }
+ LibraryInitializer(const InitializerOptions& args) { initialize(args); }
+ ~LibraryInitializer() { deinitialize(); }
+ };
+
+}
+
+#endif
diff --git a/src/core/init_def.cpp b/src/core/init_def.cpp
new file mode 100644
index 000000000..03f97252e
--- /dev/null
+++ b/src/core/init_def.cpp
@@ -0,0 +1,60 @@
+/*************************************************
+* Default Initialization Function Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/init.h>
+#include <botan/libstate.h>
+#include <botan/modules.h>
+
+namespace Botan {
+
+/*************************************************
+* Library Initialization *
+*************************************************/
+void LibraryInitializer::initialize(const InitializerOptions& args,
+ Modules& modules)
+ {
+ try
+ {
+ set_global_state(new Library_State);
+
+ global_state().initialize(args, modules);
+ }
+ catch(...)
+ {
+ deinitialize();
+ throw;
+ }
+ }
+
+/*************************************************
+* Library Shutdown *
+*************************************************/
+void LibraryInitializer::deinitialize()
+ {
+ set_global_state(0);
+ }
+
+/*************************************************
+* Library Initialization *
+*************************************************/
+void LibraryInitializer::initialize(const std::string& arg_string)
+ {
+ InitializerOptions args(arg_string);
+ Builtin_Modules modules(args);
+
+ initialize(args, modules);
+ }
+
+/*************************************************
+* Library Initialization *
+*************************************************/
+void LibraryInitializer::initialize(const InitializerOptions& args)
+ {
+ Builtin_Modules modules(args);
+
+ initialize(args, modules);
+ }
+
+}
diff --git a/src/core/init_opt.cpp b/src/core/init_opt.cpp
new file mode 100644
index 000000000..5c4fbee65
--- /dev/null
+++ b/src/core/init_opt.cpp
@@ -0,0 +1,102 @@
+/*************************************************
+* Initialization Options Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/init.h>
+#include <botan/parsing.h>
+#include <botan/stl_util.h>
+#include <botan/exceptn.h>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* Check for an arbitrary boolean-valued option *
+*************************************************/
+bool boolean_arg(const std::map<std::string, std::string>& args,
+ const std::string& key, bool not_found = false)
+ {
+ std::map<std::string, std::string>::const_iterator i = args.find(key);
+ if(i == args.end())
+ return not_found;
+
+ std::string value = i->second;
+
+ if(value == "1" || value == "true" || value == "yes" || value == "on")
+ return true;
+ if(value == "0" || value == "false" || value == "no" || value == "off")
+ return false;
+ if(value == "default")
+ return not_found;
+
+ throw Invalid_Argument("InitializerOptions: Bad argument for boolean " +
+ key + " of '" + value + "'");
+ }
+
+}
+
+/*************************************************
+* Check if thread safety was requested *
+*************************************************/
+bool InitializerOptions::thread_safe() const
+ {
+ return boolean_arg(args, "thread_safe");
+ }
+
+/*************************************************
+* Check if secure allocation was requested *
+*************************************************/
+bool InitializerOptions::secure_memory() const
+ {
+ return boolean_arg(args, "secure_memory");
+ }
+
+/*************************************************
+* Check if using engines was requested *
+*************************************************/
+bool InitializerOptions::use_engines() const
+ {
+ return boolean_arg(args, "use_engines");
+ }
+
+/*************************************************
+* Check if FIPS mode was requested *
+*************************************************/
+bool InitializerOptions::fips_mode() const
+ {
+ return boolean_arg(args, "fips140");
+ }
+
+/*************************************************
+* Check if startup self tests were requested *
+*************************************************/
+bool InitializerOptions::self_test() const
+ {
+ return boolean_arg(args, "selftest", true);
+ }
+
+/*************************************************
+* Setup an InitializerOptions *
+*************************************************/
+InitializerOptions::InitializerOptions(const std::string& arg_string)
+ {
+ const std::vector<std::string> arg_list = split_on(arg_string, ' ');
+
+ for(u32bit j = 0; j != arg_list.size(); ++j)
+ {
+ if(arg_list[j].size() == 0)
+ continue;
+
+ if(arg_list[j].find('=') == std::string::npos)
+ args[arg_list[j]] = "true";
+ else
+ {
+ std::vector<std::string> name_and_value = split_on(arg_list[j], '=');
+ args[name_and_value[0]] = name_and_value[1];
+ }
+ }
+ }
+
+}
diff --git a/src/core/kdf.cpp b/src/core/kdf.cpp
new file mode 100644
index 000000000..dca56e1a6
--- /dev/null
+++ b/src/core/kdf.cpp
@@ -0,0 +1,70 @@
+/*************************************************
+* KDF Base Class Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/pk_util.h>
+#include <botan/lookup.h>
+#include <botan/loadstor.h>
+#include <algorithm>
+#include <memory>
+
+namespace Botan {
+
+/*************************************************
+* Derive a key *
+*************************************************/
+SecureVector<byte> KDF::derive_key(u32bit key_len,
+ const MemoryRegion<byte>& secret,
+ const std::string& salt) const
+ {
+ return derive_key(key_len, secret, secret.size(),
+ reinterpret_cast<const byte*>(salt.data()),
+ salt.length());
+ }
+
+/*************************************************
+* Derive a key *
+*************************************************/
+SecureVector<byte> KDF::derive_key(u32bit key_len,
+ const MemoryRegion<byte>& secret,
+ const byte salt[], u32bit salt_len) const
+ {
+ return derive_key(key_len, secret.begin(), secret.size(),
+ salt, salt_len);
+ }
+
+/*************************************************
+* Derive a key *
+*************************************************/
+SecureVector<byte> KDF::derive_key(u32bit key_len,
+ const MemoryRegion<byte>& secret,
+ const MemoryRegion<byte>& salt) const
+ {
+ return derive_key(key_len, secret.begin(), secret.size(),
+ salt.begin(), salt.size());
+ }
+
+/*************************************************
+* Derive a key *
+*************************************************/
+SecureVector<byte> KDF::derive_key(u32bit key_len,
+ const byte secret[], u32bit secret_len,
+ const std::string& salt) const
+ {
+ return derive_key(key_len, secret, secret_len,
+ reinterpret_cast<const byte*>(salt.data()),
+ salt.length());
+ }
+
+/*************************************************
+* Derive a key *
+*************************************************/
+SecureVector<byte> KDF::derive_key(u32bit key_len,
+ const byte secret[], u32bit secret_len,
+ const byte salt[], u32bit salt_len) const
+ {
+ return derive(key_len, secret, secret_len, salt, salt_len);
+ }
+
+}
diff --git a/src/core/libstate.cpp b/src/core/libstate.cpp
new file mode 100644
index 000000000..df9d2b519
--- /dev/null
+++ b/src/core/libstate.cpp
@@ -0,0 +1,294 @@
+/*************************************************
+* Library Internal/Global State Source File *
+* (C) 1999-2008 Jack Lloyd *
+*************************************************/
+
+#include <botan/libstate.h>
+#include <botan/modules.h>
+#include <botan/engine.h>
+#include <botan/stl_util.h>
+#include <botan/mutex.h>
+#include <botan/charset.h>
+#include <botan/lookup.h>
+#include <algorithm>
+
+#if defined(BOTAN_HAS_SELFTEST)
+ #include <botan/selftest.h>
+#endif
+
+namespace Botan {
+
+/*************************************************
+* Botan's global state *
+*************************************************/
+namespace {
+
+Library_State* global_lib_state = 0;
+
+}
+
+/*************************************************
+* Access the global state object *
+*************************************************/
+Library_State& global_state()
+ {
+ if(!global_lib_state)
+ LibraryInitializer::initialize();
+ return (*global_lib_state);
+ }
+
+/*************************************************
+* Set a new global state object *
+*************************************************/
+void set_global_state(Library_State* new_state)
+ {
+ delete swap_global_state(new_state);
+ }
+
+/*************************************************
+* Swap two global state objects *
+*************************************************/
+Library_State* swap_global_state(Library_State* new_state)
+ {
+ Library_State* old_state = global_lib_state;
+ global_lib_state = new_state;
+ return old_state;
+ }
+
+/*************************************************
+* Increment the Engine iterator *
+*************************************************/
+Engine* Library_State::Engine_Iterator::next()
+ {
+ return lib.get_engine_n(n++);
+ }
+
+/*************************************************
+* Get a new mutex object *
+*************************************************/
+Mutex* Library_State::get_mutex() const
+ {
+ return mutex_factory->make();
+ }
+
+/*************************************************
+* Get an allocator by its name *
+*************************************************/
+Allocator* Library_State::get_allocator(const std::string& type) const
+ {
+ Mutex_Holder lock(allocator_lock);
+
+ if(type != "")
+ return search_map<std::string, Allocator*>(alloc_factory, type, 0);
+
+ if(!cached_default_allocator)
+ {
+ std::string chosen = this->option("base/default_allocator");
+
+ if(chosen == "")
+ chosen = "malloc";
+
+ cached_default_allocator =
+ search_map<std::string, Allocator*>(alloc_factory, chosen, 0);
+ }
+
+ return cached_default_allocator;
+ }
+
+/*************************************************
+* Create a new name to object mapping *
+*************************************************/
+void Library_State::add_allocator(Allocator* allocator)
+ {
+ Mutex_Holder lock(allocator_lock);
+
+ allocator->init();
+
+ allocators.push_back(allocator);
+ alloc_factory[allocator->type()] = allocator;
+ }
+
+/*************************************************
+* Set the default allocator type *
+*************************************************/
+void Library_State::set_default_allocator(const std::string& type)
+ {
+ Mutex_Holder lock(allocator_lock);
+
+ if(type == "")
+ return;
+
+ this->set("conf", "base/default_allocator", type);
+ cached_default_allocator = 0;
+ }
+
+/*************************************************
+* Get an engine out of the list *
+*************************************************/
+Engine* Library_State::get_engine_n(u32bit n) const
+ {
+ Mutex_Holder lock(engine_lock);
+
+ if(n >= engines.size())
+ return 0;
+ return engines[n];
+ }
+
+/*************************************************
+* Add a new engine to the list *
+*************************************************/
+void Library_State::add_engine(Engine* engine)
+ {
+ Mutex_Holder lock(engine_lock);
+ engines.insert(engines.begin(), engine);
+ }
+
+/*************************************************
+* Get a configuration value *
+*************************************************/
+std::string Library_State::get(const std::string& section,
+ const std::string& key) const
+ {
+ Mutex_Holder lock(config_lock);
+
+ return search_map<std::string, std::string>(config,
+ section + "/" + key, "");
+ }
+
+/*************************************************
+* See if a particular option has been set *
+*************************************************/
+bool Library_State::is_set(const std::string& section,
+ const std::string& key) const
+ {
+ Mutex_Holder lock(config_lock);
+
+ return search_map(config, section + "/" + key, false, true);
+ }
+
+/*************************************************
+* Set a configuration value *
+*************************************************/
+void Library_State::set(const std::string& section, const std::string& key,
+ const std::string& value, bool overwrite)
+ {
+ Mutex_Holder lock(config_lock);
+
+ std::string full_key = section + "/" + key;
+
+ std::map<std::string, std::string>::const_iterator i =
+ config.find(full_key);
+
+ if(overwrite || i == config.end() || i->second == "")
+ config[full_key] = value;
+ }
+
+/*************************************************
+* Add an alias *
+*************************************************/
+void Library_State::add_alias(const std::string& key, const std::string& value)
+ {
+ set("alias", key, value);
+ }
+
+/*************************************************
+* Dereference an alias to a fixed name *
+*************************************************/
+std::string Library_State::deref_alias(const std::string& key) const
+ {
+ std::string result = key;
+ while(is_set("alias", result))
+ result = get("alias", result);
+ return result;
+ }
+
+/*************************************************
+* Set/Add an option *
+*************************************************/
+void Library_State::set_option(const std::string key,
+ const std::string& value)
+ {
+ set("conf", key, value);
+ }
+
+/*************************************************
+* Get an option value *
+*************************************************/
+std::string Library_State::option(const std::string& key) const
+ {
+ return get("conf", key);
+ }
+
+/*************************************************
+* Load a set of modules *
+*************************************************/
+void Library_State::initialize(const InitializerOptions& args,
+ Modules& modules)
+ {
+ if(mutex_factory)
+ throw Invalid_State("Library_State has already been initialized");
+
+ mutex_factory = modules.mutex_factory(args.thread_safe());
+
+ if(!mutex_factory)
+ throw Invalid_State("Could not acquire a mutex module at init");
+
+ allocator_lock = get_mutex();
+ engine_lock = get_mutex();
+ config_lock = get_mutex();
+
+ cached_default_allocator = 0;
+
+ std::vector<Allocator*> mod_allocs = modules.allocators();
+ for(u32bit j = 0; j != mod_allocs.size(); ++j)
+ add_allocator(mod_allocs[j]);
+
+ set_default_allocator(modules.default_allocator());
+
+ load_default_config();
+
+ std::vector<Engine*> mod_engines = modules.engines();
+ for(u32bit j = 0; j != mod_engines.size(); ++j)
+ engines.push_back(mod_engines[j]);
+
+#if defined(BOTAN_HAS_SELFTEST)
+ if(args.fips_mode() || args.self_test())
+ {
+ if(!passes_self_tests())
+ throw Self_Test_Failure("Initialization self-tests");
+ }
+#endif
+ }
+
+/*************************************************
+* Library_State Constructor *
+*************************************************/
+Library_State::Library_State()
+ {
+ mutex_factory = 0;
+ allocator_lock = engine_lock = config_lock = 0;
+ cached_default_allocator = 0;
+ }
+
+/*************************************************
+* Library_State Destructor *
+*************************************************/
+Library_State::~Library_State()
+ {
+ std::for_each(engines.begin(), engines.end(), del_fun<Engine>());
+
+ cached_default_allocator = 0;
+
+ for(u32bit j = 0; j != allocators.size(); ++j)
+ {
+ allocators[j]->destroy();
+ delete allocators[j];
+ }
+
+ delete allocator_lock;
+ delete engine_lock;
+ delete mutex_factory;
+ delete config_lock;
+ }
+
+}
diff --git a/src/core/libstate.h b/src/core/libstate.h
new file mode 100644
index 000000000..4b1221c84
--- /dev/null
+++ b/src/core/libstate.h
@@ -0,0 +1,90 @@
+/*************************************************
+* Library Internal/Global State Header File *
+* (C) 1999-2008 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_LIB_STATE_H__
+#define BOTAN_LIB_STATE_H__
+
+#include <botan/base.h>
+#include <botan/init.h>
+#include <string>
+#include <vector>
+#include <map>
+
+namespace Botan {
+
+/*************************************************
+* Global State Container Base *
+*************************************************/
+class BOTAN_DLL Library_State
+ {
+ public:
+ Library_State();
+ ~Library_State();
+
+ void initialize(const InitializerOptions&, Modules&);
+
+ void load(Modules&);
+
+ void add_engine(class Engine*);
+
+ class BOTAN_DLL Engine_Iterator
+ {
+ public:
+ class Engine* next();
+ Engine_Iterator(const Library_State& l) : lib(l) { n = 0; }
+ private:
+ const Library_State& lib;
+ u32bit n;
+ };
+ friend class Engine_Iterator;
+
+ Allocator* get_allocator(const std::string& = "") const;
+ void add_allocator(Allocator*);
+ void set_default_allocator(const std::string&);
+
+ std::string get(const std::string&, const std::string&) const;
+ bool is_set(const std::string&, const std::string&) const;
+ void set(const std::string&, const std::string&,
+ const std::string&, bool = true);
+
+ std::string option(const std::string&) const;
+ void set_option(const std::string, const std::string&);
+
+ void add_alias(const std::string&, const std::string&);
+ std::string deref_alias(const std::string&) const;
+
+ class Mutex* get_mutex() const;
+ private:
+ void load_default_config();
+
+ Library_State(const Library_State&) {}
+ Library_State& operator=(const Library_State&) { return (*this); }
+
+ class Engine* get_engine_n(u32bit) const;
+
+ class Mutex_Factory* mutex_factory;
+
+ std::map<std::string, std::string> config;
+ class Mutex* config_lock;
+
+ class Mutex* allocator_lock;
+ std::map<std::string, Allocator*> alloc_factory;
+ mutable Allocator* cached_default_allocator;
+ std::vector<Allocator*> allocators;
+
+ class Mutex* engine_lock;
+ std::vector<class Engine*> engines;
+ };
+
+/*************************************************
+* Global State *
+*************************************************/
+BOTAN_DLL Library_State& global_state();
+BOTAN_DLL void set_global_state(Library_State*);
+BOTAN_DLL Library_State* swap_global_state(Library_State*);
+
+}
+
+#endif
diff --git a/src/core/look_add.h b/src/core/look_add.h
new file mode 100644
index 000000000..4185cbc0a
--- /dev/null
+++ b/src/core/look_add.h
@@ -0,0 +1,27 @@
+/*************************************************
+* Lookup Table Management Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_LOOKUP_MANGEMENT_H__
+#define BOTAN_LOOKUP_MANGEMENT_H__
+
+#include <botan/base.h>
+#include <botan/mode_pad.h>
+#include <botan/s2k.h>
+
+namespace Botan {
+
+/*************************************************
+* Add an algorithm to the lookup table *
+*************************************************/
+BOTAN_DLL void add_algorithm(BlockCipher*);
+BOTAN_DLL void add_algorithm(StreamCipher*);
+BOTAN_DLL void add_algorithm(HashFunction*);
+BOTAN_DLL void add_algorithm(MessageAuthenticationCode*);
+BOTAN_DLL void add_algorithm(S2K*);
+BOTAN_DLL void add_algorithm(BlockCipherModePaddingMethod*);
+
+}
+
+#endif
diff --git a/src/core/look_pk.cpp b/src/core/look_pk.cpp
new file mode 100644
index 000000000..a4062b57c
--- /dev/null
+++ b/src/core/look_pk.cpp
@@ -0,0 +1,74 @@
+/*************************************************
+* PK Algorithm Lookup Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/look_pk.h>
+#include <botan/lookup.h>
+
+namespace Botan {
+
+/*************************************************
+* Get a PK_Encryptor object *
+*************************************************/
+PK_Encryptor* get_pk_encryptor(const PK_Encrypting_Key& key,
+ const std::string& eme)
+ {
+ return new PK_Encryptor_MR_with_EME(key, eme);
+ }
+
+/*************************************************
+* Get a PK_Decryptor object *
+*************************************************/
+PK_Decryptor* get_pk_decryptor(const PK_Decrypting_Key& key,
+ const std::string& eme)
+ {
+ return new PK_Decryptor_MR_with_EME(key, eme);
+ }
+
+/*************************************************
+* Get a PK_Signer object *
+*************************************************/
+PK_Signer* get_pk_signer(const PK_Signing_Key& key,
+ const std::string& encoding,
+ Signature_Format sig_format)
+ {
+ PK_Signer* signer = new PK_Signer(key, encoding);
+ signer->set_output_format(sig_format);
+ return signer;
+ }
+
+/*************************************************
+* Get a PK_Verifier object *
+*************************************************/
+PK_Verifier* get_pk_verifier(const PK_Verifying_with_MR_Key& key,
+ const std::string& encoding,
+ Signature_Format sig_format)
+ {
+ PK_Verifier* verifier = new PK_Verifier_with_MR(key, encoding);
+ verifier->set_input_format(sig_format);
+ return verifier;
+ }
+
+/*************************************************
+* Get a PK_Verifier object *
+*************************************************/
+PK_Verifier* get_pk_verifier(const PK_Verifying_wo_MR_Key& key,
+ const std::string& encoding,
+ Signature_Format sig_format)
+ {
+ PK_Verifier* verifier = new PK_Verifier_wo_MR(key, encoding);
+ verifier->set_input_format(sig_format);
+ return verifier;
+ }
+
+/*************************************************
+* Get a PK_Key_Agreement object *
+*************************************************/
+PK_Key_Agreement* get_pk_kas(const PK_Key_Agreement_Key& key,
+ const std::string& kdf)
+ {
+ return new PK_Key_Agreement(key, kdf);
+ }
+
+}
diff --git a/src/core/look_pk.h b/src/core/look_pk.h
new file mode 100644
index 000000000..63756ad22
--- /dev/null
+++ b/src/core/look_pk.h
@@ -0,0 +1,38 @@
+/*************************************************
+* PK Algorithm Lookup Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_PK_LOOKUP_H__
+#define BOTAN_PK_LOOKUP_H__
+
+#include <botan/pubkey.h>
+
+namespace Botan {
+
+/*************************************************
+* Get an PK algorithm object *
+*************************************************/
+BOTAN_DLL PK_Encryptor* get_pk_encryptor(const PK_Encrypting_Key&,
+ const std::string&);
+
+BOTAN_DLL PK_Decryptor* get_pk_decryptor(const PK_Decrypting_Key&,
+ const std::string&);
+
+BOTAN_DLL PK_Signer* get_pk_signer(const PK_Signing_Key&,
+ const std::string&,
+ Signature_Format = IEEE_1363);
+
+BOTAN_DLL PK_Verifier* get_pk_verifier(const PK_Verifying_with_MR_Key&,
+ const std::string&,
+ Signature_Format = IEEE_1363);
+BOTAN_DLL PK_Verifier* get_pk_verifier(const PK_Verifying_wo_MR_Key&,
+ const std::string&,
+ Signature_Format = IEEE_1363);
+
+BOTAN_DLL PK_Key_Agreement* get_pk_kas(const PK_Key_Agreement_Key&,
+ const std::string&);
+
+}
+
+#endif
diff --git a/src/core/lookup.h b/src/core/lookup.h
new file mode 100644
index 000000000..97c2eff50
--- /dev/null
+++ b/src/core/lookup.h
@@ -0,0 +1,92 @@
+/*************************************************
+* Algorithm Lookup Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_LOOKUP_H__
+#define BOTAN_LOOKUP_H__
+
+#include <botan/base.h>
+#include <botan/enums.h>
+#include <botan/filters.h>
+#include <botan/mode_pad.h>
+#include <botan/pk_util.h>
+#include <botan/s2k.h>
+#include <botan/pbe.h>
+
+namespace Botan {
+
+/*************************************************
+* Retrieve an object from the lookup table *
+*************************************************/
+BOTAN_DLL const BlockCipher* retrieve_block_cipher(const std::string&);
+BOTAN_DLL const StreamCipher* retrieve_stream_cipher(const std::string&);
+BOTAN_DLL const HashFunction* retrieve_hash(const std::string&);
+BOTAN_DLL const MessageAuthenticationCode* retrieve_mac(const std::string&);
+BOTAN_DLL const S2K* retrieve_s2k(const std::string&);
+
+BOTAN_DLL const BlockCipherModePaddingMethod*
+retrieve_bc_pad(const std::string&);
+
+/*************************************************
+* Get an algorithm object *
+*************************************************/
+BOTAN_DLL BlockCipher* get_block_cipher(const std::string&);
+BOTAN_DLL StreamCipher* get_stream_cipher(const std::string&);
+BOTAN_DLL HashFunction* get_hash(const std::string&);
+BOTAN_DLL MessageAuthenticationCode* get_mac(const std::string&);
+BOTAN_DLL S2K* get_s2k(const std::string&);
+BOTAN_DLL const BlockCipherModePaddingMethod* get_bc_pad(const std::string&);
+
+/*************************************************
+* Get a PBE object *
+*************************************************/
+BOTAN_DLL PBE* get_pbe(const std::string&);
+BOTAN_DLL PBE* get_pbe(const OID&, DataSource&);
+
+/*************************************************
+* Get an EMSA/EME/KDF/MGF function *
+*************************************************/
+BOTAN_DLL EME* get_eme(const std::string&);
+BOTAN_DLL EMSA* get_emsa(const std::string&);
+BOTAN_DLL MGF* get_mgf(const std::string&);
+BOTAN_DLL KDF* get_kdf(const std::string&);
+
+/*************************************************
+* Get a cipher object *
+*************************************************/
+BOTAN_DLL Keyed_Filter* get_cipher(const std::string&,
+ const SymmetricKey&,
+ const InitializationVector&,
+ Cipher_Dir);
+
+BOTAN_DLL Keyed_Filter* get_cipher(const std::string&,
+ const SymmetricKey&,
+ Cipher_Dir);
+
+BOTAN_DLL Keyed_Filter* get_cipher(const std::string&, Cipher_Dir);
+
+/*************************************************
+* Check to see if an algorithm exists *
+*************************************************/
+BOTAN_DLL bool have_algorithm(const std::string&);
+
+BOTAN_DLL bool have_block_cipher(const std::string&);
+BOTAN_DLL bool have_stream_cipher(const std::string&);
+BOTAN_DLL bool have_hash(const std::string&);
+BOTAN_DLL bool have_mac(const std::string&);
+
+/*************************************************
+* Query information about an algorithm *
+*************************************************/
+BOTAN_DLL u32bit block_size_of(const std::string&);
+BOTAN_DLL u32bit output_length_of(const std::string&);
+
+BOTAN_DLL bool valid_keylength_for(u32bit, const std::string&);
+BOTAN_DLL u32bit min_keylength_of(const std::string&);
+BOTAN_DLL u32bit max_keylength_of(const std::string&);
+BOTAN_DLL u32bit keylength_multiple_of(const std::string&);
+
+}
+
+#endif
diff --git a/src/core/mlock.cpp b/src/core/mlock.cpp
new file mode 100644
index 000000000..e4456658d
--- /dev/null
+++ b/src/core/mlock.cpp
@@ -0,0 +1,24 @@
+/*************************************************
+* Memory Locking Functions Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/util.h>
+
+namespace Botan {
+
+/*************************************************
+* Lock an area of memory into RAM *
+*************************************************/
+void lock_mem(void*, u32bit)
+ {
+ }
+
+/*************************************************
+* Unlock a previously locked region of memory *
+*************************************************/
+void unlock_mem(void*, u32bit)
+ {
+ }
+
+}
diff --git a/src/core/modules.cpp b/src/core/modules.cpp
new file mode 100644
index 000000000..08ab0cdbb
--- /dev/null
+++ b/src/core/modules.cpp
@@ -0,0 +1,127 @@
+/*************************************************
+* Module Factory Source File *
+* (C) 1999-2008 Jack Lloyd *
+*************************************************/
+
+#include <botan/modules.h>
+#include <botan/defalloc.h>
+#include <botan/eng_def.h>
+#include <botan/timers.h>
+#include <botan/parsing.h>
+
+#if defined(BOTAN_HAS_MUTEX_PTHREAD)
+ #include <botan/mux_pthr.h>
+#elif defined(BOTAN_HAS_MUTEX_WIN32)
+ #include <botan/mux_win32.h>
+#elif defined(BOTAN_HAS_MUTEX_QT)
+ #include <botan/mux_qt.h>
+#endif
+
+#if defined(BOTAN_HAS_MUTEX_NOOP)
+ #include <botan/mux_noop.h>
+#endif
+
+#if defined(BOTAN_HAS_ALLOC_MMAP)
+ #include <botan/mmap_mem.h>
+#endif
+
+#if defined(BOTAN_HAS_ENGINE_GNU_MP)
+ #include <botan/eng_gmp.h>
+#endif
+
+#if defined(BOTAN_HAS_ENGINE_OPENSSL)
+ #include <botan/eng_ossl.h>
+#endif
+
+namespace Botan {
+
+/*************************************************
+* Return a mutex factory, if available *
+*************************************************/
+Mutex_Factory* Builtin_Modules::mutex_factory(bool thread_safe) const
+ {
+ if(!thread_safe)
+ {
+#if defined(BOTAN_HAS_MUTEX_NOOP)
+ return new Noop_Mutex_Factory;
+#endif
+ }
+
+#if defined(BOTAN_HAS_MUTEX_PTHREAD)
+ return new Pthread_Mutex_Factory;
+#elif defined(BOTAN_HAS_MUTEX_WIN32)
+ return new Win32_Mutex_Factory;
+#elif defined(BOTAN_HAS_MUTEX_QT)
+ return new Qt_Mutex_Factory;
+#else
+ return 0;
+#endif
+ }
+
+/*************************************************
+* Find any usable allocators *
+*************************************************/
+std::vector<Allocator*> Builtin_Modules::allocators() const
+ {
+ std::vector<Allocator*> allocators;
+
+#if defined(BOTAN_HAS_ALLOC_MMAP)
+ allocators.push_back(new MemoryMapping_Allocator);
+#endif
+
+ allocators.push_back(new Locking_Allocator);
+ allocators.push_back(new Malloc_Allocator);
+
+ return allocators;
+ }
+
+/*************************************************
+* Return the default allocator *
+*************************************************/
+std::string Builtin_Modules::default_allocator() const
+ {
+ if(should_lock)
+ {
+#if defined(BOTAN_HAS_ALLOC_MMAP)
+ return "mmap";
+#else
+ return "locking";
+#endif
+ }
+ else
+ return "malloc";
+ }
+
+/*************************************************
+* Find any usable engines *
+*************************************************/
+std::vector<Engine*> Builtin_Modules::engines() const
+ {
+ std::vector<Engine*> engines;
+
+ if(use_engines)
+ {
+#if defined(BOTAN_HAS_ENGINE_GNU_MP)
+ engines.push_back(new GMP_Engine);
+#endif
+
+#if defined(BOTAN_HAS_ENGINE_OPENSSL)
+ engines.push_back(new OpenSSL_Engine);
+#endif
+ }
+
+ engines.push_back(new Default_Engine);
+
+ return engines;
+ }
+
+/*************************************************
+* Builtin_Modules Constructor *
+*************************************************/
+Builtin_Modules::Builtin_Modules(const InitializerOptions& args) :
+ should_lock(args.secure_memory()),
+ use_engines(args.use_engines())
+ {
+ }
+
+}
diff --git a/src/core/modules.h b/src/core/modules.h
new file mode 100644
index 000000000..69a6e1ffb
--- /dev/null
+++ b/src/core/modules.h
@@ -0,0 +1,51 @@
+/*************************************************
+* Module Factory Header File *
+* (C) 1999-2008 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_MODULE_FACTORIES_H__
+#define BOTAN_MODULE_FACTORIES_H__
+
+#include <botan/init.h>
+#include <string>
+#include <vector>
+
+namespace Botan {
+
+/*************************************************
+* Module Builder Interface *
+*************************************************/
+class BOTAN_DLL Modules
+ {
+ public:
+ virtual class Mutex_Factory* mutex_factory(bool) const = 0;
+
+ virtual std::string default_allocator() const = 0;
+
+ virtual std::vector<class Allocator*> allocators() const = 0;
+ virtual std::vector<class Engine*> engines() const = 0;
+
+ virtual ~Modules() {}
+ };
+
+/*************************************************
+* Built In Modules *
+*************************************************/
+class BOTAN_DLL Builtin_Modules : public Modules
+ {
+ public:
+ class Mutex_Factory* mutex_factory(bool) const;
+
+ std::string default_allocator() const;
+
+ std::vector<class Allocator*> allocators() const;
+ std::vector<class Engine*> engines() const;
+
+ Builtin_Modules(const InitializerOptions&);
+ private:
+ const bool should_lock, use_engines;
+ };
+
+}
+
+#endif
diff --git a/src/core/mutex.h b/src/core/mutex.h
new file mode 100644
index 000000000..e30b48eb0
--- /dev/null
+++ b/src/core/mutex.h
@@ -0,0 +1,54 @@
+/*************************************************
+* Mutex Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_MUTEX_H__
+#define BOTAN_MUTEX_H__
+
+#include <botan/exceptn.h>
+
+namespace Botan {
+
+/*************************************************
+* Mutex Base Class *
+*************************************************/
+class BOTAN_DLL Mutex
+ {
+ public:
+ virtual void lock() = 0;
+ virtual void unlock() = 0;
+ virtual ~Mutex() {}
+ };
+
+/*************************************************
+* Mutex Factory *
+*************************************************/
+class BOTAN_DLL Mutex_Factory
+ {
+ public:
+ virtual Mutex* make() = 0;
+ virtual ~Mutex_Factory() {}
+ };
+
+/*************************************************
+* Mutex Holding Class *
+*************************************************/
+class BOTAN_DLL Mutex_Holder
+ {
+ public:
+ Mutex_Holder(Mutex* m) : mux(m)
+ {
+ if(!mux)
+ throw Invalid_Argument("Mutex_Holder: Argument was NULL");
+ mux->lock();
+ }
+
+ ~Mutex_Holder() { mux->unlock(); }
+ private:
+ Mutex* mux;
+ };
+
+}
+
+#endif
diff --git a/src/core/nr_op.cpp b/src/core/nr_op.cpp
new file mode 100644
index 000000000..01e96a822
--- /dev/null
+++ b/src/core/nr_op.cpp
@@ -0,0 +1,104 @@
+/*************************************************
+* NR Operations Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/eng_def.h>
+#include <botan/pow_mod.h>
+#include <botan/numthry.h>
+#include <botan/reducer.h>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* Default NR Operation *
+*************************************************/
+class Default_NR_Op : public NR_Operation
+ {
+ public:
+ SecureVector<byte> verify(const byte[], u32bit) const;
+ SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const;
+
+ NR_Operation* clone() const { return new Default_NR_Op(*this); }
+
+ Default_NR_Op(const DL_Group&, const BigInt&, const BigInt&);
+ private:
+ const BigInt x, y;
+ const DL_Group group;
+ Fixed_Base_Power_Mod powermod_g_p, powermod_y_p;
+ Modular_Reducer mod_p, mod_q;
+ };
+
+/*************************************************
+* Default_NR_Op Constructor *
+*************************************************/
+Default_NR_Op::Default_NR_Op(const DL_Group& grp, const BigInt& y1,
+ const BigInt& x1) : x(x1), y(y1), group(grp)
+ {
+ powermod_g_p = Fixed_Base_Power_Mod(group.get_g(), group.get_p());
+ powermod_y_p = Fixed_Base_Power_Mod(y, group.get_p());
+ mod_p = Modular_Reducer(group.get_p());
+ mod_q = Modular_Reducer(group.get_q());
+ }
+
+/*************************************************
+* Default NR Verify Operation *
+*************************************************/
+SecureVector<byte> Default_NR_Op::verify(const byte in[], u32bit length) const
+ {
+ const BigInt& q = group.get_q();
+
+ if(length != 2*q.bytes())
+ return false;
+
+ BigInt c(in, q.bytes());
+ BigInt d(in + q.bytes(), q.bytes());
+
+ if(c.is_zero() || c >= q || d >= q)
+ throw Invalid_Argument("Default_NR_Op::verify: Invalid signature");
+
+ BigInt i = mod_p.multiply(powermod_g_p(d), powermod_y_p(c));
+ return BigInt::encode(mod_q.reduce(c - i));
+ }
+
+/*************************************************
+* Default NR Sign Operation *
+*************************************************/
+SecureVector<byte> Default_NR_Op::sign(const byte in[], u32bit length,
+ const BigInt& k) const
+ {
+ if(x == 0)
+ throw Internal_Error("Default_NR_Op::sign: No private key");
+
+ const BigInt& q = group.get_q();
+
+ BigInt f(in, length);
+
+ if(f >= q)
+ throw Invalid_Argument("Default_NR_Op::sign: Input is out of range");
+
+ BigInt c = mod_q.reduce(powermod_g_p(k) + f);
+ if(c.is_zero())
+ throw Internal_Error("Default_NR_Op::sign: c was zero");
+ BigInt d = mod_q.reduce(k - x * c);
+
+ SecureVector<byte> output(2*q.bytes());
+ c.binary_encode(output + (output.size() / 2 - c.bytes()));
+ d.binary_encode(output + (output.size() - d.bytes()));
+ return output;
+ }
+
+}
+
+/*************************************************
+* Acquire a NR op *
+*************************************************/
+NR_Operation* Default_Engine::nr_op(const DL_Group& group, const BigInt& y,
+ const BigInt& x) const
+ {
+ return new Default_NR_Op(group, y, x);
+ }
+
+}
diff --git a/src/core/oids.cpp b/src/core/oids.cpp
new file mode 100644
index 000000000..0823625ea
--- /dev/null
+++ b/src/core/oids.cpp
@@ -0,0 +1,74 @@
+/*************************************************
+* OID Registry Source File *
+* (C) 1999-2008 Jack Lloyd *
+*************************************************/
+
+#include <botan/oids.h>
+#include <botan/libstate.h>
+
+namespace Botan {
+
+namespace OIDS {
+
+/*************************************************
+* Register an OID to string mapping *
+*************************************************/
+void add_oid(const OID& oid, const std::string& name)
+ {
+ const std::string oid_str = oid.as_string();
+
+ if(!global_state().is_set("oid2str", oid_str))
+ global_state().set("oid2str", oid_str, name);
+ if(!global_state().is_set("str2oid", name))
+ global_state().set("str2oid", name, oid_str);
+ }
+
+/*************************************************
+* Do an OID to string lookup *
+*************************************************/
+std::string lookup(const OID& oid)
+ {
+ std::string name = global_state().get("oid2str", oid.as_string());
+ if(name == "")
+ return oid.as_string();
+ return name;
+ }
+
+/*************************************************
+* Do a string to OID lookup *
+*************************************************/
+OID lookup(const std::string& name)
+ {
+ std::string value = global_state().get("str2oid", name);
+ if(value != "")
+ return OID(value);
+
+ try
+ {
+ return OID(name);
+ }
+ catch(Exception)
+ {
+ throw Lookup_Error("No object identifier found for " + name);
+ }
+ }
+
+/*************************************************
+* Check to see if an OID exists in the table *
+*************************************************/
+bool have_oid(const std::string& name)
+ {
+ return global_state().is_set("str2oid", name);
+ }
+
+/*************************************************
+* Check to see if an OID exists in the table *
+*************************************************/
+bool name_of(const OID& oid, const std::string& name)
+ {
+ return (oid == lookup(name));
+ }
+
+}
+
+}
diff --git a/src/core/oids.h b/src/core/oids.h
new file mode 100644
index 000000000..b5be0e01f
--- /dev/null
+++ b/src/core/oids.h
@@ -0,0 +1,36 @@
+/*************************************************
+* OID Registry Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_OIDS_H__
+#define BOTAN_OIDS_H__
+
+#include <botan/asn1_oid.h>
+
+namespace Botan {
+
+namespace OIDS {
+
+/*************************************************
+* Register an OID to string mapping *
+*************************************************/
+BOTAN_DLL void add_oid(const OID&, const std::string&);
+
+/*************************************************
+* See if an OID exists in the internal table *
+*************************************************/
+BOTAN_DLL bool have_oid(const std::string&);
+
+/*************************************************
+* Perform OID<->string mappings *
+*************************************************/
+BOTAN_DLL std::string lookup(const OID&);
+BOTAN_DLL OID lookup(const std::string&);
+BOTAN_DLL bool name_of(const OID&, const std::string&);
+
+}
+
+}
+
+#endif
diff --git a/src/core/pk_algs.cpp b/src/core/pk_algs.cpp
new file mode 100644
index 000000000..83ceb61c7
--- /dev/null
+++ b/src/core/pk_algs.cpp
@@ -0,0 +1,98 @@
+/*************************************************
+* PK Key Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/pk_algs.h>
+
+#ifdef BOTAN_HAS_RSA
+ #include <botan/rsa.h>
+#endif
+
+#ifdef BOTAN_HAS_DSA
+ #include <botan/dsa.h>
+#endif
+
+#ifdef BOTAN_HAS_DH
+ #include <botan/dh.h>
+#endif
+
+#ifdef BOTAN_HAS_NR
+ #include <botan/nr.h>
+#endif
+
+#ifdef BOTAN_HAS_RW
+ #include <botan/rw.h>
+#endif
+
+#ifdef BOTAN_HAS_ELGAMAL
+ #include <botan/elgamal.h>
+#endif
+
+namespace Botan {
+
+/*************************************************
+* Get an PK public key object *
+*************************************************/
+Public_Key* get_public_key(const std::string& alg_name)
+ {
+#if defined(BOTAN_HAS_RSA)
+ if(alg_name == "RSA") return new RSA_PublicKey;
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ if(alg_name == "DSA") return new DSA_PublicKey;
+#endif
+
+#if defined(BOTAN_HAS_DH)
+ if(alg_name == "DH") return new DH_PublicKey;
+#endif
+
+#if defined(BOTAN_HAS_NR)
+ if(alg_name == "NR") return new NR_PublicKey;
+#endif
+
+#if defined(BOTAN_HAS_RW)
+ if(alg_name == "RW") return new RW_PublicKey;
+#endif
+
+#if defined(BOTAN_HAS_ELG)
+ if(alg_name == "ELG") return new ElGamal_PublicKey;
+#endif
+
+ return 0;
+ }
+
+/*************************************************
+* Get an PK private key object *
+*************************************************/
+Private_Key* get_private_key(const std::string& alg_name)
+ {
+#if defined(BOTAN_HAS_RSA)
+ if(alg_name == "RSA") return new RSA_PrivateKey;
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ if(alg_name == "DSA") return new DSA_PrivateKey;
+#endif
+
+#if defined(BOTAN_HAS_DH)
+ if(alg_name == "DH") return new DH_PrivateKey;
+#endif
+
+#if defined(BOTAN_HAS_NR)
+ if(alg_name == "NR") return new NR_PrivateKey;
+#endif
+
+#if defined(BOTAN_HAS_RW)
+ if(alg_name == "RW") return new RW_PrivateKey;
+#endif
+
+#if defined(BOTAN_HAS_ELG)
+ if(alg_name == "ELG") return new ElGamal_PrivateKey;
+#endif
+
+ return 0;
+ }
+
+}
diff --git a/src/core/pk_algs.h b/src/core/pk_algs.h
new file mode 100644
index 000000000..a8fa5f176
--- /dev/null
+++ b/src/core/pk_algs.h
@@ -0,0 +1,22 @@
+/*************************************************
+* PK Key Factory Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_PK_KEY_FACTORY_H__
+#define BOTAN_PK_KEY_FACTORY_H__
+
+#include <botan/x509_key.h>
+#include <botan/pkcs8.h>
+
+namespace Botan {
+
+/*************************************************
+* Get an PK key object *
+*************************************************/
+BOTAN_DLL Public_Key* get_public_key(const std::string&);
+BOTAN_DLL Private_Key* get_private_key(const std::string&);
+
+}
+
+#endif
diff --git a/src/core/pk_core.cpp b/src/core/pk_core.cpp
new file mode 100644
index 000000000..82fe4c217
--- /dev/null
+++ b/src/core/pk_core.cpp
@@ -0,0 +1,300 @@
+/*************************************************
+* PK Algorithm Core Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/pk_core.h>
+#include <botan/numthry.h>
+#include <botan/engine.h>
+#include <botan/parsing.h>
+#include <algorithm>
+
+namespace Botan {
+
+namespace {
+
+const u32bit BLINDING_BITS = BOTAN_PRIVATE_KEY_OP_BLINDING_BITS;
+
+}
+
+/*************************************************
+* IF_Core Constructor *
+*************************************************/
+IF_Core::IF_Core(const BigInt& e, const BigInt& n)
+ {
+ op = Engine_Core::if_op(e, n, 0, 0, 0, 0, 0, 0);
+ }
+
+
+/*************************************************
+* IF_Core Constructor *
+*************************************************/
+IF_Core::IF_Core(RandomNumberGenerator& rng,
+ const BigInt& e, const BigInt& n, const BigInt& d,
+ const BigInt& p, const BigInt& q,
+ const BigInt& d1, const BigInt& d2, const BigInt& c)
+ {
+ op = Engine_Core::if_op(e, n, d, p, q, d1, d2, c);
+
+ if(BLINDING_BITS)
+ {
+ BigInt k(rng, std::min(n.bits()-1, BLINDING_BITS));
+ blinder = Blinder(power_mod(k, e, n), inverse_mod(k, n), n);
+ }
+ }
+
+/*************************************************
+* IF_Core Copy Constructor *
+*************************************************/
+IF_Core::IF_Core(const IF_Core& core)
+ {
+ op = 0;
+ if(core.op)
+ op = core.op->clone();
+ blinder = core.blinder;
+ }
+
+/*************************************************
+* IF_Core Assignment Operator *
+*************************************************/
+IF_Core& IF_Core::operator=(const IF_Core& core)
+ {
+ delete op;
+ if(core.op)
+ op = core.op->clone();
+ blinder = core.blinder;
+ return (*this);
+ }
+
+/*************************************************
+* IF Public Operation *
+*************************************************/
+BigInt IF_Core::public_op(const BigInt& i) const
+ {
+ return op->public_op(i);
+ }
+
+/*************************************************
+* IF Private Operation *
+*************************************************/
+BigInt IF_Core::private_op(const BigInt& i) const
+ {
+ return blinder.unblind(op->private_op(blinder.blind(i)));
+ }
+
+/*************************************************
+* DSA_Core Constructor *
+*************************************************/
+DSA_Core::DSA_Core(const DL_Group& group, const BigInt& y, const BigInt& x)
+ {
+ op = Engine_Core::dsa_op(group, y, x);
+ }
+
+/*************************************************
+* DSA_Core Copy Constructor *
+*************************************************/
+DSA_Core::DSA_Core(const DSA_Core& core)
+ {
+ op = 0;
+ if(core.op)
+ op = core.op->clone();
+ }
+
+/*************************************************
+* DSA_Core Assignment Operator *
+*************************************************/
+DSA_Core& DSA_Core::operator=(const DSA_Core& core)
+ {
+ delete op;
+ if(core.op)
+ op = core.op->clone();
+ return (*this);
+ }
+
+/*************************************************
+* DSA Verification Operation *
+*************************************************/
+bool DSA_Core::verify(const byte msg[], u32bit msg_length,
+ const byte sig[], u32bit sig_length) const
+ {
+ return op->verify(msg, msg_length, sig, sig_length);
+ }
+
+/*************************************************
+* DSA Signature Operation *
+*************************************************/
+SecureVector<byte> DSA_Core::sign(const byte in[], u32bit length,
+ const BigInt& k) const
+ {
+ return op->sign(in, length, k);
+ }
+
+/*************************************************
+* NR_Core Constructor *
+*************************************************/
+NR_Core::NR_Core(const DL_Group& group, const BigInt& y, const BigInt& x)
+ {
+ op = Engine_Core::nr_op(group, y, x);
+ }
+
+/*************************************************
+* NR_Core Copy Constructor *
+*************************************************/
+NR_Core::NR_Core(const NR_Core& core)
+ {
+ op = 0;
+ if(core.op)
+ op = core.op->clone();
+ }
+
+/*************************************************
+* NR_Core Assignment Operator *
+*************************************************/
+NR_Core& NR_Core::operator=(const NR_Core& core)
+ {
+ delete op;
+ if(core.op)
+ op = core.op->clone();
+ return (*this);
+ }
+
+/*************************************************
+* NR Verification Operation *
+*************************************************/
+SecureVector<byte> NR_Core::verify(const byte in[], u32bit length) const
+ {
+ return op->verify(in, length);
+ }
+
+/*************************************************
+* NR Signature Operation *
+*************************************************/
+SecureVector<byte> NR_Core::sign(const byte in[], u32bit length,
+ const BigInt& k) const
+ {
+ return op->sign(in, length, k);
+ }
+
+/*************************************************
+* ELG_Core Constructor *
+*************************************************/
+ELG_Core::ELG_Core(const DL_Group& group, const BigInt& y)
+ {
+ op = Engine_Core::elg_op(group, y, 0);
+ p_bytes = 0;
+ }
+
+/*************************************************
+* ELG_Core Constructor *
+*************************************************/
+ELG_Core::ELG_Core(RandomNumberGenerator& rng,
+ const DL_Group& group, const BigInt& y, const BigInt& x)
+ {
+ op = Engine_Core::elg_op(group, y, x);
+
+ const BigInt& p = group.get_p();
+ p_bytes = p.bytes();
+
+ if(BLINDING_BITS)
+ {
+ BigInt k(rng, std::min(p.bits()-1, BLINDING_BITS));
+ blinder = Blinder(k, power_mod(k, x, p), p);
+ }
+ }
+
+/*************************************************
+* ELG_Core Copy Constructor *
+*************************************************/
+ELG_Core::ELG_Core(const ELG_Core& core)
+ {
+ op = 0;
+ if(core.op)
+ op = core.op->clone();
+ blinder = core.blinder;
+ p_bytes = core.p_bytes;
+ }
+
+/*************************************************
+* ELG_Core Assignment Operator *
+*************************************************/
+ELG_Core& ELG_Core::operator=(const ELG_Core& core)
+ {
+ delete op;
+ if(core.op)
+ op = core.op->clone();
+ blinder = core.blinder;
+ p_bytes = core.p_bytes;
+ return (*this);
+ }
+
+/*************************************************
+* ElGamal Encrypt Operation *
+*************************************************/
+SecureVector<byte> ELG_Core::encrypt(const byte in[], u32bit length,
+ const BigInt& k) const
+ {
+ return op->encrypt(in, length, k);
+ }
+
+/*************************************************
+* ElGamal Decrypt Operation *
+*************************************************/
+SecureVector<byte> ELG_Core::decrypt(const byte in[], u32bit length) const
+ {
+ if(length != 2*p_bytes)
+ throw Invalid_Argument("ELG_Core::decrypt: Invalid message");
+
+ BigInt a(in, p_bytes);
+ BigInt b(in + p_bytes, p_bytes);
+
+ return BigInt::encode(blinder.unblind(op->decrypt(blinder.blind(a), b)));
+ }
+
+/*************************************************
+* DH_Core Constructor *
+*************************************************/
+DH_Core::DH_Core(RandomNumberGenerator& rng,
+ const DL_Group& group, const BigInt& x)
+ {
+ op = Engine_Core::dh_op(group, x);
+
+ const BigInt& p = group.get_p();
+
+ BigInt k(rng, std::min(p.bits()-1, BLINDING_BITS));
+
+ if(k != 0)
+ blinder = Blinder(k, power_mod(inverse_mod(k, p), x, p), p);
+ }
+
+/*************************************************
+* DH_Core Copy Constructor *
+*************************************************/
+DH_Core::DH_Core(const DH_Core& core)
+ {
+ op = 0;
+ if(core.op)
+ op = core.op->clone();
+ blinder = core.blinder;
+ }
+
+/*************************************************
+* DH_Core Assignment Operator *
+*************************************************/
+DH_Core& DH_Core::operator=(const DH_Core& core)
+ {
+ delete op;
+ if(core.op)
+ op = core.op->clone();
+ blinder = core.blinder;
+ return (*this);
+ }
+
+/*************************************************
+* DH Operation *
+*************************************************/
+BigInt DH_Core::agree(const BigInt& i) const
+ {
+ return blinder.unblind(op->agree(blinder.blind(i)));
+ }
+
+}
diff --git a/src/core/pk_core.h b/src/core/pk_core.h
new file mode 100644
index 000000000..585c12ee4
--- /dev/null
+++ b/src/core/pk_core.h
@@ -0,0 +1,128 @@
+/*************************************************
+* PK Algorithm Core Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_PK_CORE_H__
+#define BOTAN_PK_CORE_H__
+
+#include <botan/bigint.h>
+#include <botan/dl_group.h>
+#include <botan/blinding.h>
+#include <botan/pk_ops.h>
+
+namespace Botan {
+
+/*************************************************
+* IF Core *
+*************************************************/
+class BOTAN_DLL IF_Core
+ {
+ public:
+ BigInt public_op(const BigInt&) const;
+ BigInt private_op(const BigInt&) const;
+
+ IF_Core& operator=(const IF_Core&);
+
+ IF_Core() { op = 0; }
+ IF_Core(const IF_Core&);
+
+ IF_Core(const BigInt&, const BigInt&);
+
+ IF_Core(RandomNumberGenerator& rng,
+ const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&, const BigInt&);
+
+ ~IF_Core() { delete op; }
+ private:
+ IF_Operation* op;
+ Blinder blinder;
+ };
+
+/*************************************************
+* DSA Core *
+*************************************************/
+class BOTAN_DLL DSA_Core
+ {
+ public:
+ SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const;
+ bool verify(const byte[], u32bit, const byte[], u32bit) const;
+
+ DSA_Core& operator=(const DSA_Core&);
+
+ DSA_Core() { op = 0; }
+ DSA_Core(const DSA_Core&);
+ DSA_Core(const DL_Group&, const BigInt&, const BigInt& = 0);
+ ~DSA_Core() { delete op; }
+ private:
+ DSA_Operation* op;
+ };
+
+/*************************************************
+* NR Core *
+*************************************************/
+class BOTAN_DLL NR_Core
+ {
+ public:
+ SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const;
+ SecureVector<byte> verify(const byte[], u32bit) const;
+
+ NR_Core& operator=(const NR_Core&);
+
+ NR_Core() { op = 0; }
+ NR_Core(const NR_Core&);
+ NR_Core(const DL_Group&, const BigInt&, const BigInt& = 0);
+ ~NR_Core() { delete op; }
+ private:
+ NR_Operation* op;
+ };
+
+/*************************************************
+* ElGamal Core *
+*************************************************/
+class BOTAN_DLL ELG_Core
+ {
+ public:
+ SecureVector<byte> encrypt(const byte[], u32bit, const BigInt&) const;
+ SecureVector<byte> decrypt(const byte[], u32bit) const;
+
+ ELG_Core& operator=(const ELG_Core&);
+
+ ELG_Core() { op = 0; }
+ ELG_Core(const ELG_Core&);
+
+ ELG_Core(const DL_Group&, const BigInt&);
+ ELG_Core(RandomNumberGenerator&, const DL_Group&,
+ const BigInt&, const BigInt&);
+
+ ~ELG_Core() { delete op; }
+ private:
+ ELG_Operation* op;
+ Blinder blinder;
+ u32bit p_bytes;
+ };
+
+/*************************************************
+* DH Core *
+*************************************************/
+class BOTAN_DLL DH_Core
+ {
+ public:
+ BigInt agree(const BigInt&) const;
+
+ DH_Core& operator=(const DH_Core&);
+
+ DH_Core() { op = 0; }
+ DH_Core(const DH_Core&);
+ DH_Core(RandomNumberGenerator& rng,
+ const DL_Group&, const BigInt&);
+ ~DH_Core() { delete op; }
+ private:
+ DH_Operation* op;
+ Blinder blinder;
+ };
+
+}
+
+#endif
diff --git a/src/core/pk_keys.cpp b/src/core/pk_keys.cpp
new file mode 100644
index 000000000..d991f3788
--- /dev/null
+++ b/src/core/pk_keys.cpp
@@ -0,0 +1,68 @@
+/*************************************************
+* PK Key Types Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/pk_keys.h>
+#include <botan/libstate.h>
+#include <botan/oids.h>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* Find out how much testing should be performed *
+*************************************************/
+bool key_check_level(const std::string& type)
+ {
+ const std::string setting = global_state().option("pk/test/" + type);
+ if(setting == "basic")
+ return false;
+ return true;
+ }
+
+}
+
+/*************************************************
+* Default OID access *
+*************************************************/
+OID Public_Key::get_oid() const
+ {
+ try {
+ return OIDS::lookup(algo_name());
+ }
+ catch(Lookup_Error)
+ {
+ throw Lookup_Error("PK algo " + algo_name() + " has no defined OIDs");
+ }
+ }
+
+/*************************************************
+* Run checks on a loaded public key *
+*************************************************/
+void Public_Key::load_check(RandomNumberGenerator& rng) const
+ {
+ if(!check_key(rng, key_check_level("public")))
+ throw Invalid_Argument(algo_name() + ": Invalid public key");
+ }
+
+/*************************************************
+* Run checks on a loaded private key *
+*************************************************/
+void Private_Key::load_check(RandomNumberGenerator& rng) const
+ {
+ if(!check_key(rng, key_check_level("private")))
+ throw Invalid_Argument(algo_name() + ": Invalid private key");
+ }
+
+/*************************************************
+* Run checks on a generated private key *
+*************************************************/
+void Private_Key::gen_check(RandomNumberGenerator& rng) const
+ {
+ if(!check_key(rng, key_check_level("private_gen")))
+ throw Self_Test_Failure(algo_name() + " private key generation failed");
+ }
+
+}
diff --git a/src/core/pk_keys.h b/src/core/pk_keys.h
new file mode 100644
index 000000000..16109c634
--- /dev/null
+++ b/src/core/pk_keys.h
@@ -0,0 +1,127 @@
+/*************************************************
+* PK Key Types Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_PK_KEYS_H__
+#define BOTAN_PK_KEYS_H__
+
+#include <botan/secmem.h>
+#include <botan/asn1_oid.h>
+#include <botan/rng.h>
+
+namespace Botan {
+
+/*************************************************
+* Public Key Base Class *
+*************************************************/
+class BOTAN_DLL Public_Key
+ {
+ public:
+ virtual std::string algo_name() const = 0;
+ virtual OID get_oid() const;
+
+ virtual bool check_key(RandomNumberGenerator&, bool) const
+ { return true; }
+
+ virtual u32bit message_parts() const { return 1; }
+ virtual u32bit message_part_size() const { return 0; }
+ virtual u32bit max_input_bits() const = 0;
+
+ virtual class X509_Encoder* x509_encoder() const = 0;
+ virtual class X509_Decoder* x509_decoder() = 0;
+
+ virtual ~Public_Key() {}
+ protected:
+ virtual void load_check(RandomNumberGenerator&) const;
+ };
+
+/*************************************************
+* Private Key Base Class *
+*************************************************/
+class BOTAN_DLL Private_Key : public virtual Public_Key
+ {
+ public:
+ virtual class PKCS8_Encoder* pkcs8_encoder() const
+ { return 0; }
+ virtual class PKCS8_Decoder* pkcs8_decoder(RandomNumberGenerator&)
+ { return 0; }
+ protected:
+ void load_check(RandomNumberGenerator&) const;
+ void gen_check(RandomNumberGenerator&) const;
+ };
+
+/*************************************************
+* PK Encrypting Key *
+*************************************************/
+class BOTAN_DLL PK_Encrypting_Key : public virtual Public_Key
+ {
+ public:
+ virtual SecureVector<byte> encrypt(const byte[], u32bit,
+ RandomNumberGenerator&) const = 0;
+ virtual ~PK_Encrypting_Key() {}
+ };
+
+/*************************************************
+* PK Decrypting Key *
+*************************************************/
+class BOTAN_DLL PK_Decrypting_Key : public virtual Private_Key
+ {
+ public:
+ virtual SecureVector<byte> decrypt(const byte[], u32bit) const = 0;
+ virtual ~PK_Decrypting_Key() {}
+ };
+
+/*************************************************
+* PK Signing Key *
+*************************************************/
+class BOTAN_DLL PK_Signing_Key : public virtual Private_Key
+ {
+ public:
+ virtual SecureVector<byte> sign(const byte[], u32bit,
+ RandomNumberGenerator& rng) const = 0;
+ virtual ~PK_Signing_Key() {}
+ };
+
+/*************************************************
+* PK Verifying Key, Message Recovery Version *
+*************************************************/
+class BOTAN_DLL PK_Verifying_with_MR_Key : public virtual Public_Key
+ {
+ public:
+ virtual SecureVector<byte> verify(const byte[], u32bit) const = 0;
+ virtual ~PK_Verifying_with_MR_Key() {}
+ };
+
+/*************************************************
+* PK Verifying Key, No Message Recovery Version *
+*************************************************/
+class BOTAN_DLL PK_Verifying_wo_MR_Key : public virtual Public_Key
+ {
+ public:
+ virtual bool verify(const byte[], u32bit,
+ const byte[], u32bit) const = 0;
+ virtual ~PK_Verifying_wo_MR_Key() {}
+ };
+
+/*************************************************
+* PK Secret Value Derivation Key *
+*************************************************/
+class BOTAN_DLL PK_Key_Agreement_Key : public virtual Private_Key
+ {
+ public:
+ virtual SecureVector<byte> derive_key(const byte[], u32bit) const = 0;
+ virtual MemoryVector<byte> public_value() const = 0;
+ virtual ~PK_Key_Agreement_Key() {}
+ };
+
+/*************************************************
+* Typedefs *
+*************************************************/
+typedef PK_Key_Agreement_Key PK_KA_Key;
+typedef Public_Key X509_PublicKey;
+typedef Private_Key PKCS8_PrivateKey;
+
+}
+
+#endif
diff --git a/src/core/pk_ops.h b/src/core/pk_ops.h
new file mode 100644
index 000000000..fad87b573
--- /dev/null
+++ b/src/core/pk_ops.h
@@ -0,0 +1,79 @@
+/*************************************************
+* Public Key Operations Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_PK_OPS_H__
+#define BOTAN_PK_OPS_H__
+
+#include <botan/bigint.h>
+#include <botan/dl_group.h>
+
+namespace Botan {
+
+/*************************************************
+* IF Operation *
+*************************************************/
+class BOTAN_DLL IF_Operation
+ {
+ public:
+ virtual BigInt public_op(const BigInt&) const = 0;
+ virtual BigInt private_op(const BigInt&) const = 0;
+ virtual IF_Operation* clone() const = 0;
+ virtual ~IF_Operation() {}
+ };
+
+/*************************************************
+* DSA Operation *
+*************************************************/
+class BOTAN_DLL DSA_Operation
+ {
+ public:
+ virtual bool verify(const byte[], u32bit,
+ const byte[], u32bit) const = 0;
+ virtual SecureVector<byte> sign(const byte[], u32bit,
+ const BigInt&) const = 0;
+ virtual DSA_Operation* clone() const = 0;
+ virtual ~DSA_Operation() {}
+ };
+
+/*************************************************
+* NR Operation *
+*************************************************/
+class BOTAN_DLL NR_Operation
+ {
+ public:
+ virtual SecureVector<byte> verify(const byte[], u32bit) const = 0;
+ virtual SecureVector<byte> sign(const byte[], u32bit,
+ const BigInt&) const = 0;
+ virtual NR_Operation* clone() const = 0;
+ virtual ~NR_Operation() {}
+ };
+
+/*************************************************
+* ElGamal Operation *
+*************************************************/
+class BOTAN_DLL ELG_Operation
+ {
+ public:
+ virtual SecureVector<byte> encrypt(const byte[], u32bit,
+ const BigInt&) const = 0;
+ virtual BigInt decrypt(const BigInt&, const BigInt&) const = 0;
+ virtual ELG_Operation* clone() const = 0;
+ virtual ~ELG_Operation() {}
+ };
+
+/*************************************************
+* DH Operation *
+*************************************************/
+class BOTAN_DLL DH_Operation
+ {
+ public:
+ virtual BigInt agree(const BigInt&) const = 0;
+ virtual DH_Operation* clone() const = 0;
+ virtual ~DH_Operation() {}
+ };
+
+}
+
+#endif
diff --git a/src/core/pk_util.cpp b/src/core/pk_util.cpp
new file mode 100644
index 000000000..1976436ea
--- /dev/null
+++ b/src/core/pk_util.cpp
@@ -0,0 +1,48 @@
+/*************************************************
+* PK Utility Classes Source File *
+* (C) 1999-2008 Jack Lloyd *
+*************************************************/
+
+#include <botan/pk_util.h>
+
+namespace Botan {
+
+/*************************************************
+* Encode a message *
+*************************************************/
+SecureVector<byte> EME::encode(const byte msg[], u32bit msg_len,
+ u32bit key_bits,
+ RandomNumberGenerator& rng) const
+ {
+ return pad(msg, msg_len, key_bits, rng);
+ }
+
+/*************************************************
+* Encode a message *
+*************************************************/
+SecureVector<byte> EME::encode(const MemoryRegion<byte>& msg,
+ u32bit key_bits,
+ RandomNumberGenerator& rng) const
+ {
+ return pad(msg, msg.size(), key_bits, rng);
+ }
+
+/*************************************************
+* Decode a message *
+*************************************************/
+SecureVector<byte> EME::decode(const byte msg[], u32bit msg_len,
+ u32bit key_bits) const
+ {
+ return unpad(msg, msg_len, key_bits);
+ }
+
+/*************************************************
+* Decode a message *
+*************************************************/
+SecureVector<byte> EME::decode(const MemoryRegion<byte>& msg,
+ u32bit key_bits) const
+ {
+ return unpad(msg, msg.size(), key_bits);
+ }
+
+}
diff --git a/src/core/pk_util.h b/src/core/pk_util.h
new file mode 100644
index 000000000..aa7a71234
--- /dev/null
+++ b/src/core/pk_util.h
@@ -0,0 +1,92 @@
+/*************************************************
+* PK Utility Classes Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_PUBKEY_UTIL_H__
+#define BOTAN_PUBKEY_UTIL_H__
+
+#include <botan/base.h>
+#include <botan/rng.h>
+
+namespace Botan {
+
+/*************************************************
+* Encoding Method for Encryption *
+*************************************************/
+class BOTAN_DLL EME
+ {
+ public:
+ virtual u32bit maximum_input_size(u32bit) const = 0;
+
+ SecureVector<byte> encode(const byte[], u32bit, u32bit,
+ RandomNumberGenerator&) const;
+ SecureVector<byte> encode(const MemoryRegion<byte>&, u32bit,
+ RandomNumberGenerator&) const;
+
+ SecureVector<byte> decode(const byte[], u32bit, u32bit) const;
+ SecureVector<byte> decode(const MemoryRegion<byte>&, u32bit) const;
+
+ virtual ~EME() {}
+ private:
+ virtual SecureVector<byte> pad(const byte[], u32bit, u32bit,
+ RandomNumberGenerator&) const = 0;
+
+ virtual SecureVector<byte> unpad(const byte[], u32bit, u32bit) const = 0;
+ };
+
+/*************************************************
+* Encoding Method for Signatures, Appendix *
+*************************************************/
+class BOTAN_DLL EMSA
+ {
+ public:
+ virtual void update(const byte[], u32bit) = 0;
+ virtual SecureVector<byte> raw_data() = 0;
+
+ virtual SecureVector<byte> encoding_of(const MemoryRegion<byte>&,
+ u32bit,
+ RandomNumberGenerator& rng) = 0;
+
+ virtual bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&,
+ u32bit) throw() = 0;
+ virtual ~EMSA() {}
+ };
+
+/*************************************************
+* Key Derivation Function *
+*************************************************/
+class BOTAN_DLL KDF
+ {
+ public:
+ SecureVector<byte> derive_key(u32bit, const MemoryRegion<byte>&,
+ const std::string& = "") const;
+ SecureVector<byte> derive_key(u32bit, const MemoryRegion<byte>&,
+ const MemoryRegion<byte>&) const;
+ SecureVector<byte> derive_key(u32bit, const MemoryRegion<byte>&,
+ const byte[], u32bit) const;
+
+ SecureVector<byte> derive_key(u32bit, const byte[], u32bit,
+ const std::string& = "") const;
+ SecureVector<byte> derive_key(u32bit, const byte[], u32bit,
+ const byte[], u32bit) const;
+
+ virtual ~KDF() {}
+ private:
+ virtual SecureVector<byte> derive(u32bit, const byte[], u32bit,
+ const byte[], u32bit) const = 0;
+ };
+
+/*************************************************
+* Mask Generation Function *
+*************************************************/
+class BOTAN_DLL MGF
+ {
+ public:
+ virtual void mask(const byte[], u32bit, byte[], u32bit) const = 0;
+ virtual ~MGF() {}
+ };
+
+}
+
+#endif
diff --git a/src/core/pkcs8.cpp b/src/core/pkcs8.cpp
new file mode 100644
index 000000000..2963c9d86
--- /dev/null
+++ b/src/core/pkcs8.cpp
@@ -0,0 +1,307 @@
+/*************************************************
+* PKCS #8 Source File *
+* (C) 1999-2008 Jack Lloyd *
+*************************************************/
+
+#include <botan/pkcs8.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/asn1_obj.h>
+#include <botan/pk_algs.h>
+#include <botan/oids.h>
+#include <botan/pem.h>
+#include <botan/lookup.h>
+#include <memory>
+
+namespace Botan {
+
+namespace PKCS8 {
+
+namespace {
+
+/*************************************************
+* Get info from an EncryptedPrivateKeyInfo *
+*************************************************/
+SecureVector<byte> PKCS8_extract(DataSource& source,
+ AlgorithmIdentifier& pbe_alg_id)
+ {
+ SecureVector<byte> key_data;
+
+ BER_Decoder(source)
+ .start_cons(SEQUENCE)
+ .decode(pbe_alg_id)
+ .decode(key_data, OCTET_STRING)
+ .verify_end();
+
+ return key_data;
+ }
+
+/*************************************************
+* PEM decode and/or decrypt a private key *
+*************************************************/
+SecureVector<byte> PKCS8_decode(DataSource& source, const User_Interface& ui,
+ AlgorithmIdentifier& pk_alg_id)
+ {
+ AlgorithmIdentifier pbe_alg_id;
+ SecureVector<byte> key_data, key;
+ bool is_encrypted = true;
+
+ try {
+ if(ASN1::maybe_BER(source) && !PEM_Code::matches(source))
+ key_data = PKCS8_extract(source, pbe_alg_id);
+ else
+ {
+ std::string label;
+ key_data = PEM_Code::decode(source, label);
+ if(label == "PRIVATE KEY")
+ is_encrypted = false;
+ else if(label == "ENCRYPTED PRIVATE KEY")
+ {
+ DataSource_Memory key_source(key_data);
+ key_data = PKCS8_extract(key_source, pbe_alg_id);
+ }
+ else
+ throw PKCS8_Exception("Unknown PEM label " + label);
+ }
+
+ if(key_data.is_empty())
+ throw PKCS8_Exception("No key data found");
+ }
+ catch(Decoding_Error)
+ {
+ throw Decoding_Error("PKCS #8 private key decoding failed");
+ }
+
+ if(!is_encrypted)
+ key = key_data;
+
+ const u32bit MAX_TRIES = 3;
+
+ u32bit tries = 0;
+ while(true)
+ {
+ try {
+ if(MAX_TRIES && tries >= MAX_TRIES)
+ break;
+
+ if(is_encrypted)
+ {
+ DataSource_Memory params(pbe_alg_id.parameters);
+ PBE* pbe = get_pbe(pbe_alg_id.oid, params);
+
+ User_Interface::UI_Result result = User_Interface::OK;
+ const std::string passphrase =
+ ui.get_passphrase("PKCS #8 private key", source.id(), result);
+
+ if(result == User_Interface::CANCEL_ACTION)
+ break;
+
+ pbe->set_key(passphrase);
+ Pipe decryptor(pbe);
+ decryptor.process_msg(key_data, key_data.size());
+ key = decryptor.read_all();
+ }
+
+ u32bit version;
+
+ BER_Decoder(key)
+ .start_cons(SEQUENCE)
+ .decode(version)
+ .decode(pk_alg_id)
+ .decode(key, OCTET_STRING)
+ .discard_remaining()
+ .end_cons();
+
+ if(version != 0)
+ throw Decoding_Error("PKCS #8: Unknown version number");
+
+ break;
+ }
+ catch(Decoding_Error)
+ {
+ ++tries;
+ }
+ }
+
+ if(key.is_empty())
+ throw Decoding_Error("PKCS #8 private key decoding failed");
+ return key;
+ }
+
+}
+
+/*************************************************
+* DER or PEM encode a PKCS #8 private key *
+*************************************************/
+void encode(const Private_Key& key, Pipe& pipe, X509_Encoding encoding)
+ {
+ std::auto_ptr<PKCS8_Encoder> encoder(key.pkcs8_encoder());
+ if(!encoder.get())
+ throw Encoding_Error("PKCS8::encode: Key does not support encoding");
+
+ const u32bit PKCS8_VERSION = 0;
+
+ SecureVector<byte> contents =
+ DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(PKCS8_VERSION)
+ .encode(encoder->alg_id())
+ .encode(encoder->key_bits(), OCTET_STRING)
+ .end_cons()
+ .get_contents();
+
+ if(encoding == PEM)
+ pipe.write(PEM_Code::encode(contents, "PRIVATE KEY"));
+ else
+ pipe.write(contents);
+ }
+
+/*************************************************
+* Encode and encrypt a PKCS #8 private key *
+*************************************************/
+void encrypt_key(const Private_Key& key,
+ Pipe& pipe,
+ RandomNumberGenerator& rng,
+ const std::string& pass, const std::string& pbe_algo,
+ X509_Encoding encoding)
+ {
+ const std::string DEFAULT_PBE = "PBE-PKCS5v20(SHA-1,TripleDES/CBC)";
+
+ Pipe raw_key;
+ raw_key.start_msg();
+ encode(key, raw_key, RAW_BER);
+ raw_key.end_msg();
+
+ PBE* pbe = get_pbe(((pbe_algo != "") ? pbe_algo : DEFAULT_PBE));
+ pbe->new_params(rng);
+ pbe->set_key(pass);
+
+ Pipe key_encrytor(pbe);
+ key_encrytor.process_msg(raw_key);
+
+ SecureVector<byte> enc_key =
+ DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(AlgorithmIdentifier(pbe->get_oid(), pbe->encode_params()))
+ .encode(key_encrytor.read_all(), OCTET_STRING)
+ .end_cons()
+ .get_contents();
+
+ if(encoding == PEM)
+ pipe.write(PEM_Code::encode(enc_key, "ENCRYPTED PRIVATE KEY"));
+ else
+ pipe.write(enc_key);
+ }
+
+/*************************************************
+* PEM encode a PKCS #8 private key *
+*************************************************/
+std::string PEM_encode(const Private_Key& key)
+ {
+ Pipe pem;
+ pem.start_msg();
+ encode(key, pem, PEM);
+ pem.end_msg();
+ return pem.read_all_as_string();
+ }
+
+/*************************************************
+* Encrypt and PEM encode a PKCS #8 private key *
+*************************************************/
+std::string PEM_encode(const Private_Key& key,
+ RandomNumberGenerator& rng,
+ const std::string& pass,
+ const std::string& pbe_algo)
+ {
+ if(pass == "")
+ return PEM_encode(key);
+
+ Pipe pem;
+ pem.start_msg();
+ encrypt_key(key, pem, rng, pass, pbe_algo, PEM);
+ pem.end_msg();
+ return pem.read_all_as_string();
+ }
+
+/*************************************************
+* Extract a private key and return it *
+*************************************************/
+Private_Key* load_key(DataSource& source,
+ RandomNumberGenerator& rng,
+ const User_Interface& ui)
+ {
+ AlgorithmIdentifier alg_id;
+ SecureVector<byte> pkcs8_key = PKCS8_decode(source, ui, alg_id);
+
+ const std::string alg_name = OIDS::lookup(alg_id.oid);
+ if(alg_name == "" || alg_name == alg_id.oid.as_string())
+ throw PKCS8_Exception("Unknown algorithm OID: " +
+ alg_id.oid.as_string());
+
+ std::auto_ptr<Private_Key> key(get_private_key(alg_name));
+
+ if(!key.get())
+ throw PKCS8_Exception("Unknown PK algorithm/OID: " + alg_name + ", " +
+ alg_id.oid.as_string());
+
+ std::auto_ptr<PKCS8_Decoder> decoder(key->pkcs8_decoder(rng));
+
+ if(!decoder.get())
+ throw Decoding_Error("Key does not support PKCS #8 decoding");
+
+ decoder->alg_id(alg_id);
+ decoder->key_bits(pkcs8_key);
+
+ return key.release();
+ }
+
+/*************************************************
+* Extract a private key and return it *
+*************************************************/
+Private_Key* load_key(const std::string& fsname,
+ RandomNumberGenerator& rng,
+ const User_Interface& ui)
+ {
+ DataSource_Stream source(fsname, true);
+ return PKCS8::load_key(source, rng, ui);
+ }
+
+/*************************************************
+* Extract a private key and return it *
+*************************************************/
+Private_Key* load_key(DataSource& source,
+ RandomNumberGenerator& rng,
+ const std::string& pass)
+ {
+ return PKCS8::load_key(source, rng, User_Interface(pass));
+ }
+
+/*************************************************
+* Extract a private key and return it *
+*************************************************/
+Private_Key* load_key(const std::string& fsname,
+ RandomNumberGenerator& rng,
+ const std::string& pass)
+ {
+ return PKCS8::load_key(fsname, rng, User_Interface(pass));
+ }
+
+/*************************************************
+* Make a copy of this private key *
+*************************************************/
+Private_Key* copy_key(const Private_Key& key,
+ RandomNumberGenerator& rng)
+ {
+ Pipe bits;
+
+ bits.start_msg();
+ PKCS8::encode(key, bits);
+ bits.end_msg();
+
+ DataSource_Memory source(bits.read_all());
+ return PKCS8::load_key(source, rng);
+ }
+
+}
+
+}
diff --git a/src/core/pkcs8.h b/src/core/pkcs8.h
new file mode 100644
index 000000000..383b1604a
--- /dev/null
+++ b/src/core/pkcs8.h
@@ -0,0 +1,85 @@
+/*************************************************
+* PKCS #8 Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_PKCS8_H__
+#define BOTAN_PKCS8_H__
+
+#include <botan/x509_key.h>
+#include <botan/ui.h>
+#include <botan/enums.h>
+
+namespace Botan {
+
+/*************************************************
+* PKCS #8 Private Key Encoder *
+*************************************************/
+class BOTAN_DLL PKCS8_Encoder
+ {
+ public:
+ virtual AlgorithmIdentifier alg_id() const = 0;
+ virtual MemoryVector<byte> key_bits() const = 0;
+ virtual ~PKCS8_Encoder() {}
+ };
+
+/*************************************************
+* PKCS #8 Private Key Decoder *
+*************************************************/
+class BOTAN_DLL PKCS8_Decoder
+ {
+ public:
+ virtual void alg_id(const AlgorithmIdentifier&) = 0;
+ virtual void key_bits(const MemoryRegion<byte>&) = 0;
+ virtual ~PKCS8_Decoder() {}
+ };
+
+/*************************************************
+* PKCS #8 General Exception *
+*************************************************/
+struct BOTAN_DLL PKCS8_Exception : public Decoding_Error
+ {
+ PKCS8_Exception(const std::string& error) :
+ Decoding_Error("PKCS #8: " + error) {}
+ };
+
+namespace PKCS8 {
+
+/*************************************************
+* PKCS #8 Private Key Encoding/Decoding *
+*************************************************/
+BOTAN_DLL void encode(const Private_Key&, Pipe&, X509_Encoding = PEM);
+BOTAN_DLL std::string PEM_encode(const Private_Key&);
+
+BOTAN_DLL void encrypt_key(const Private_Key&,
+ Pipe&,
+ RandomNumberGenerator&,
+ const std::string&,
+ const std::string& = "",
+ X509_Encoding = PEM);
+
+BOTAN_DLL std::string PEM_encode(const Private_Key&,
+ RandomNumberGenerator&,
+ const std::string&,
+ const std::string& = "");
+
+BOTAN_DLL Private_Key* load_key(DataSource&, RandomNumberGenerator&,
+ const User_Interface&);
+BOTAN_DLL Private_Key* load_key(DataSource&, RandomNumberGenerator&,
+ const std::string& = "");
+
+BOTAN_DLL Private_Key* load_key(const std::string&,
+ RandomNumberGenerator&,
+ const User_Interface&);
+BOTAN_DLL Private_Key* load_key(const std::string&,
+ RandomNumberGenerator&,
+ const std::string& = "");
+
+BOTAN_DLL Private_Key* copy_key(const Private_Key&,
+ RandomNumberGenerator& rng);
+
+}
+
+}
+
+#endif
diff --git a/src/core/policy.cpp b/src/core/policy.cpp
new file mode 100644
index 000000000..f1c844017
--- /dev/null
+++ b/src/core/policy.cpp
@@ -0,0 +1,500 @@
+/*************************************************
+* Default Policy Source File *
+* (C) 1999-2008 Jack Lloyd *
+*************************************************/
+
+#include <botan/libstate.h>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* OID loading helper function *
+*************************************************/
+void add_oid(Library_State& config,
+ const std::string& oid_str,
+ const std::string& name)
+ {
+ if(!config.is_set("oid2str", oid_str))
+ config.set("oid2str", oid_str, name);
+ if(!config.is_set("str2oid", name))
+ config.set("str2oid", name, oid_str);
+ }
+
+/*************************************************
+* Load all of the default OIDs *
+*************************************************/
+void set_default_oids(Library_State& config)
+ {
+ add_oid(config, "1.2.840.113549.1.1.1", "RSA");
+ add_oid(config, "2.5.8.1.1", "RSA");
+ add_oid(config, "1.2.840.10040.4.1", "DSA");
+ add_oid(config, "1.2.840.10046.2.1", "DH");
+ add_oid(config, "1.3.6.1.4.1.3029.1.2.1", "ELG");
+ add_oid(config, "1.3.6.1.4.1.25258.1.1", "RW");
+ add_oid(config, "1.3.6.1.4.1.25258.1.2", "NR");
+
+ add_oid(config, "1.3.14.3.2.7", "DES/CBC");
+ add_oid(config, "1.2.840.113549.3.7", "TripleDES/CBC");
+ add_oid(config, "1.2.840.113549.3.2", "RC2/CBC");
+ add_oid(config, "1.2.840.113533.7.66.10", "CAST-128/CBC");
+ add_oid(config, "2.16.840.1.101.3.4.1.2", "AES-128/CBC");
+ add_oid(config, "2.16.840.1.101.3.4.1.22", "AES-192/CBC");
+ add_oid(config, "2.16.840.1.101.3.4.1.42", "AES-256/CBC");
+
+ add_oid(config, "1.2.840.113549.2.5", "MD5");
+ add_oid(config, "1.3.6.1.4.1.11591.12.2", "Tiger(24,3)");
+
+ add_oid(config, "1.3.14.3.2.26", "SHA-160");
+ add_oid(config, "2.16.840.1.101.3.4.2.4", "SHA-224");
+ add_oid(config, "2.16.840.1.101.3.4.2.1", "SHA-256");
+ add_oid(config, "2.16.840.1.101.3.4.2.2", "SHA-384");
+ add_oid(config, "2.16.840.1.101.3.4.2.3", "SHA-512");
+
+ add_oid(config, "1.2.840.113549.1.9.16.3.6", "KeyWrap.TripleDES");
+ add_oid(config, "1.2.840.113549.1.9.16.3.7", "KeyWrap.RC2");
+ add_oid(config, "1.2.840.113533.7.66.15", "KeyWrap.CAST-128");
+ add_oid(config, "2.16.840.1.101.3.4.1.5", "KeyWrap.AES-128");
+ add_oid(config, "2.16.840.1.101.3.4.1.25", "KeyWrap.AES-192");
+ add_oid(config, "2.16.840.1.101.3.4.1.45", "KeyWrap.AES-256");
+
+ add_oid(config, "1.2.840.113549.1.9.16.3.8", "Compression.Zlib");
+
+ add_oid(config, "1.2.840.113549.1.1.1", "RSA/EME-PKCS1-v1_5");
+ add_oid(config, "1.2.840.113549.1.1.2", "RSA/EMSA3(MD2)");
+ add_oid(config, "1.2.840.113549.1.1.4", "RSA/EMSA3(MD5)");
+ add_oid(config, "1.2.840.113549.1.1.5", "RSA/EMSA3(SHA-160)");
+ add_oid(config, "1.2.840.113549.1.1.11", "RSA/EMSA3(SHA-256)");
+ add_oid(config, "1.2.840.113549.1.1.12", "RSA/EMSA3(SHA-384)");
+ add_oid(config, "1.2.840.113549.1.1.13", "RSA/EMSA3(SHA-512)");
+ add_oid(config, "1.3.36.3.3.1.2", "RSA/EMSA3(RIPEMD-160)");
+
+ add_oid(config, "1.2.840.10040.4.3", "DSA/EMSA1(SHA-160)");
+ add_oid(config, "2.16.840.1.101.3.4.3.1", "DSA/EMSA1(SHA-224)");
+ add_oid(config, "2.16.840.1.101.3.4.3.2", "DSA/EMSA1(SHA-256)");
+
+ add_oid(config, "1.3.6.1.4.1.25258.2.1.1.1", "RW/EMSA2(RIPEMD-160)");
+ add_oid(config, "1.3.6.1.4.1.25258.2.1.1.2", "RW/EMSA2(SHA-160)");
+ add_oid(config, "1.3.6.1.4.1.25258.2.1.1.3", "RW/EMSA2(SHA-224)");
+ add_oid(config, "1.3.6.1.4.1.25258.2.1.1.4", "RW/EMSA2(SHA-256)");
+ add_oid(config, "1.3.6.1.4.1.25258.2.1.1.5", "RW/EMSA2(SHA-384)");
+ add_oid(config, "1.3.6.1.4.1.25258.2.1.1.6", "RW/EMSA2(SHA-512)");
+
+ add_oid(config, "1.3.6.1.4.1.25258.2.1.2.1", "RW/EMSA4(RIPEMD-160)");
+ add_oid(config, "1.3.6.1.4.1.25258.2.1.2.2", "RW/EMSA4(SHA-160)");
+ add_oid(config, "1.3.6.1.4.1.25258.2.1.2.3", "RW/EMSA4(SHA-224)");
+ add_oid(config, "1.3.6.1.4.1.25258.2.1.2.4", "RW/EMSA4(SHA-256)");
+ add_oid(config, "1.3.6.1.4.1.25258.2.1.2.5", "RW/EMSA4(SHA-384)");
+ add_oid(config, "1.3.6.1.4.1.25258.2.1.2.6", "RW/EMSA4(SHA-512)");
+
+ add_oid(config, "1.3.6.1.4.1.25258.2.2.1.1", "NR/EMSA2(RIPEMD-160)");
+ add_oid(config, "1.3.6.1.4.1.25258.2.2.1.2", "NR/EMSA2(SHA-160)");
+ add_oid(config, "1.3.6.1.4.1.25258.2.2.1.3", "NR/EMSA2(SHA-224)");
+ add_oid(config, "1.3.6.1.4.1.25258.2.2.1.4", "NR/EMSA2(SHA-256)");
+ add_oid(config, "1.3.6.1.4.1.25258.2.2.1.5", "NR/EMSA2(SHA-384)");
+ add_oid(config, "1.3.6.1.4.1.25258.2.2.1.6", "NR/EMSA2(SHA-512)");
+
+ add_oid(config, "2.5.4.3", "X520.CommonName");
+ add_oid(config, "2.5.4.4", "X520.Surname");
+ add_oid(config, "2.5.4.5", "X520.SerialNumber");
+ add_oid(config, "2.5.4.6", "X520.Country");
+ add_oid(config, "2.5.4.7", "X520.Locality");
+ add_oid(config, "2.5.4.8", "X520.State");
+ add_oid(config, "2.5.4.10", "X520.Organization");
+ add_oid(config, "2.5.4.11", "X520.OrganizationalUnit");
+ add_oid(config, "2.5.4.12", "X520.Title");
+ add_oid(config, "2.5.4.42", "X520.GivenName");
+ add_oid(config, "2.5.4.43", "X520.Initials");
+ add_oid(config, "2.5.4.44", "X520.GenerationalQualifier");
+ add_oid(config, "2.5.4.46", "X520.DNQualifier");
+ add_oid(config, "2.5.4.65", "X520.Pseudonym");
+
+ add_oid(config, "1.2.840.113549.1.5.12", "PKCS5.PBKDF2");
+ add_oid(config, "1.2.840.113549.1.5.1", "PBE-PKCS5v15(MD2,DES/CBC)");
+ add_oid(config, "1.2.840.113549.1.5.4", "PBE-PKCS5v15(MD2,RC2/CBC)");
+ add_oid(config, "1.2.840.113549.1.5.3", "PBE-PKCS5v15(MD5,DES/CBC)");
+ add_oid(config, "1.2.840.113549.1.5.6", "PBE-PKCS5v15(MD5,RC2/CBC)");
+ add_oid(config, "1.2.840.113549.1.5.10", "PBE-PKCS5v15(SHA-160,DES/CBC)");
+ add_oid(config, "1.2.840.113549.1.5.11", "PBE-PKCS5v15(SHA-160,RC2/CBC)");
+ add_oid(config, "1.2.840.113549.1.5.13", "PBE-PKCS5v20");
+
+ add_oid(config, "1.2.840.113549.1.9.1", "PKCS9.EmailAddress");
+ add_oid(config, "1.2.840.113549.1.9.2", "PKCS9.UnstructuredName");
+ add_oid(config, "1.2.840.113549.1.9.3", "PKCS9.ContentType");
+ add_oid(config, "1.2.840.113549.1.9.4", "PKCS9.MessageDigest");
+ add_oid(config, "1.2.840.113549.1.9.7", "PKCS9.ChallengePassword");
+ add_oid(config, "1.2.840.113549.1.9.14", "PKCS9.ExtensionRequest");
+
+ add_oid(config, "1.2.840.113549.1.7.1", "CMS.DataContent");
+ add_oid(config, "1.2.840.113549.1.7.2", "CMS.SignedData");
+ add_oid(config, "1.2.840.113549.1.7.3", "CMS.EnvelopedData");
+ add_oid(config, "1.2.840.113549.1.7.5", "CMS.DigestedData");
+ add_oid(config, "1.2.840.113549.1.7.6", "CMS.EncryptedData");
+ add_oid(config, "1.2.840.113549.1.9.16.1.2", "CMS.AuthenticatedData");
+ add_oid(config, "1.2.840.113549.1.9.16.1.9", "CMS.CompressedData");
+
+ add_oid(config, "2.5.29.14", "X509v3.SubjectKeyIdentifier");
+ add_oid(config, "2.5.29.15", "X509v3.KeyUsage");
+ add_oid(config, "2.5.29.17", "X509v3.SubjectAlternativeName");
+ add_oid(config, "2.5.29.18", "X509v3.IssuerAlternativeName");
+ add_oid(config, "2.5.29.19", "X509v3.BasicConstraints");
+ add_oid(config, "2.5.29.20", "X509v3.CRLNumber");
+ add_oid(config, "2.5.29.21", "X509v3.ReasonCode");
+ add_oid(config, "2.5.29.23", "X509v3.HoldInstructionCode");
+ add_oid(config, "2.5.29.24", "X509v3.InvalidityDate");
+ add_oid(config, "2.5.29.32", "X509v3.CertificatePolicies");
+ add_oid(config, "2.5.29.35", "X509v3.AuthorityKeyIdentifier");
+ add_oid(config, "2.5.29.36", "X509v3.PolicyConstraints");
+ add_oid(config, "2.5.29.37", "X509v3.ExtendedKeyUsage");
+
+ add_oid(config, "2.5.29.32.0", "X509v3.AnyPolicy");
+
+ add_oid(config, "1.3.6.1.5.5.7.3.1", "PKIX.ServerAuth");
+ add_oid(config, "1.3.6.1.5.5.7.3.2", "PKIX.ClientAuth");
+ add_oid(config, "1.3.6.1.5.5.7.3.3", "PKIX.CodeSigning");
+ add_oid(config, "1.3.6.1.5.5.7.3.4", "PKIX.EmailProtection");
+ add_oid(config, "1.3.6.1.5.5.7.3.5", "PKIX.IPsecEndSystem");
+ add_oid(config, "1.3.6.1.5.5.7.3.6", "PKIX.IPsecTunnel");
+ add_oid(config, "1.3.6.1.5.5.7.3.7", "PKIX.IPsecUser");
+ add_oid(config, "1.3.6.1.5.5.7.3.8", "PKIX.TimeStamping");
+ add_oid(config, "1.3.6.1.5.5.7.3.9", "PKIX.OCSPSigning");
+
+ add_oid(config, "1.3.6.1.5.5.7.8.5", "PKIX.XMPPAddr");
+ }
+
+/*************************************************
+* Set the default algorithm aliases *
+*************************************************/
+void set_default_aliases(Library_State& config)
+ {
+ config.add_alias("OpenPGP.Cipher.1", "IDEA");
+ config.add_alias("OpenPGP.Cipher.2", "TripleDES");
+ config.add_alias("OpenPGP.Cipher.3", "CAST-128");
+ config.add_alias("OpenPGP.Cipher.4", "Blowfish");
+ config.add_alias("OpenPGP.Cipher.5", "SAFER-SK(13)");
+ config.add_alias("OpenPGP.Cipher.7", "AES-128");
+ config.add_alias("OpenPGP.Cipher.8", "AES-192");
+ config.add_alias("OpenPGP.Cipher.9", "AES-256");
+ config.add_alias("OpenPGP.Cipher.10", "Twofish");
+
+ config.add_alias("OpenPGP.Digest.1", "MD5");
+ config.add_alias("OpenPGP.Digest.2", "SHA-1");
+ config.add_alias("OpenPGP.Digest.3", "RIPEMD-160");
+ config.add_alias("OpenPGP.Digest.5", "MD2");
+ config.add_alias("OpenPGP.Digest.6", "Tiger(24,3)");
+ config.add_alias("OpenPGP.Digest.7", "HAVAL(20,5)");
+ config.add_alias("OpenPGP.Digest.8", "SHA-256");
+
+ config.add_alias("TLS.Digest.0", "Parallel(MD5,SHA-160)");
+
+ config.add_alias("EME-PKCS1-v1_5", "PKCS1v15");
+ config.add_alias("OAEP-MGF1", "EME1");
+ config.add_alias("EME-OAEP", "EME1");
+ config.add_alias("X9.31", "EMSA2");
+ config.add_alias("EMSA-PKCS1-v1_5", "EMSA3");
+ config.add_alias("PSS-MGF1", "EMSA4");
+ config.add_alias("EMSA-PSS", "EMSA4");
+
+ config.add_alias("Rijndael", "AES");
+ config.add_alias("3DES", "TripleDES");
+ config.add_alias("DES-EDE", "TripleDES");
+ config.add_alias("CAST5", "CAST-128");
+ config.add_alias("SHA1", "SHA-160");
+ config.add_alias("SHA-1", "SHA-160");
+ config.add_alias("SEAL", "SEAL-3.0-BE");
+ config.add_alias("MARK-4", "ARC4(256)");
+ config.add_alias("OMAC", "CMAC");
+ }
+
+/*************************************************
+* Set the default configuration toggles *
+*************************************************/
+void set_default_config(Library_State& config)
+ {
+ config.set_option("base/default_allocator", "malloc");
+
+ config.set_option("pk/test/public", "basic");
+ config.set_option("pk/test/private", "basic");
+ config.set_option("pk/test/private_gen", "all");
+
+ config.set_option("x509/ca/allow_ca", "false");
+ config.set_option("x509/ca/basic_constraints", "always");
+ config.set_option("x509/ca/rsa_hash", "SHA-1");
+ config.set_option("x509/ca/str_type", "latin1");
+
+ config.set_option("x509/crl/unknown_critical", "ignore");
+ config.set_option("x509/crl/next_update", "7d");
+
+ config.set_option("x509/exts/basic_constraints", "critical");
+ config.set_option("x509/exts/subject_key_id", "yes");
+ config.set_option("x509/exts/authority_key_id", "yes");
+ config.set_option("x509/exts/subject_alternative_name", "yes");
+ config.set_option("x509/exts/issuer_alternative_name", "no");
+ config.set_option("x509/exts/key_usage", "critical");
+ config.set_option("x509/exts/extended_key_usage", "yes");
+ config.set_option("x509/exts/crl_number", "yes");
+ }
+
+/*************************************************
+* Set the built-in discrete log groups *
+*************************************************/
+void set_default_dl_groups(Library_State& config)
+ {
+ config.set("dl", "modp/ietf/768",
+ "-----BEGIN X942 DH PARAMETERS-----"
+ "MIHIAmEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxObIlFK"
+ "CHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjo2IP//"
+ "////////AgECAmB//////////+SH7VEQtGEaYmMxRcBuDmiUgScERTPmOgEF31Md"
+ "ic2RKKUEPMcaAm73yozZ5p0hjZgVhTb5L4obp/Catrao4SLyQtq7MS8/Y3omIXTT"
+ "HRsQf/////////8="
+ "-----END X942 DH PARAMETERS-----");
+
+ config.set("dl", "modp/ietf/1024",
+ "-----BEGIN X942 DH PARAMETERS-----"
+ "MIIBCgKBgQD//////////8kP2qIhaMI0xMZii4DcHNEpAk4IimfMdAILvqY7E5si"
+ "UUoIeY40BN3vlRmzzTpDGzArCm3yXxQ3T+E1bW1RwkXkhbV2Yl5+xvRMQummN+1r"
+ "C/9ctvQGt+3uOGv7Womfpa6fJBF8Sx/mSShmUezmU4H//////////wIBAgKBgH//"
+ "////////5IftURC0YRpiYzFFwG4OaJSBJwRFM+Y6AQXfUx2JzZEopQQ8xxoCbvfK"
+ "jNnmnSGNmBWFNvkvihun8Jq2tqjhIvJC2rsxLz9jeiYhdNMb9rWF/65begNb9vcc"
+ "Nf2tRM/S10+SCL4lj/MklDMo9nMpwP//////////"
+ "-----END X942 DH PARAMETERS-----");
+
+ config.set("dl", "modp/ietf/1536",
+ "-----BEGIN X942 DH PARAMETERS-----"
+ "MIIBigKBwQD//////////8kP2qIhaMI0xMZii4DcHNEpAk4IimfMdAILvqY7E5si"
+ "UUoIeY40BN3vlRmzzTpDGzArCm3yXxQ3T+E1bW1RwkXkhbV2Yl5+xvRMQummN+1r"
+ "C/9ctvQGt+3uOGv7Womfpa6fJBF8Sx/mSShmUezkWz3CAHy4oWO/BZjaSDYcVdOa"
+ "aRY/qP0kz1+DZV0j3KOtlhxi81YghVK7ntUpB3CWlm1nDDVOSryYBPF0bAjKI3Mn"
+ "//////////8CAQICgcB//////////+SH7VEQtGEaYmMxRcBuDmiUgScERTPmOgEF"
+ "31Mdic2RKKUEPMcaAm73yozZ5p0hjZgVhTb5L4obp/Catrao4SLyQtq7MS8/Y3om"
+ "IXTTG/a1hf+uW3oDW/b3HDX9rUTP0tdPkgi+JY/zJJQzKPZyLZ7hAD5cULHfgsxt"
+ "JBsOKunNNIsf1H6SZ6/Bsq6R7lHWyw4xeasQQqldz2qUg7hLSzazhhqnJV5MAni6"
+ "NgRlEbmT//////////8="
+ "-----END X942 DH PARAMETERS-----");
+
+ config.set("dl", "modp/ietf/2048",
+ "-----BEGIN X942 DH PARAMETERS-----"
+ "MIICDAKCAQEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb"
+ "IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft"
+ "awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT"
+ "mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh"
+ "fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq"
+ "5RXSJhiY+gUQFXKOWoqsqmj//////////wIBAgKCAQB//////////+SH7VEQtGEa"
+ "YmMxRcBuDmiUgScERTPmOgEF31Mdic2RKKUEPMcaAm73yozZ5p0hjZgVhTb5L4ob"
+ "p/Catrao4SLyQtq7MS8/Y3omIXTTG/a1hf+uW3oDW/b3HDX9rUTP0tdPkgi+JY/z"
+ "JJQzKPZyLZ7hAD5cULHfgsxtJBsOKunNNIsf1H6SZ6/Bsq6R7lHWyw4xeasQQqld"
+ "z2qUg7hLSzazhhqnJV5MAni6NgRlDBC+GUgvIxcbZx3xzzuWDAdDAc2TwdF2A9FH"
+ "2uKu+DemKWTvFeX7SqwLjBzKpL51SrVyiukTDEx9AogKuUctRVZVNH//////////"
+ "-----END X942 DH PARAMETERS-----");
+
+ config.set("dl", "modp/ietf/3072",
+ "-----BEGIN X942 DH PARAMETERS-----"
+ "MIIDDAKCAYEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb"
+ "IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft"
+ "awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT"
+ "mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh"
+ "fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq"
+ "5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM"
+ "fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq"
+ "ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqTrS"
+ "yv//////////AgECAoIBgH//////////5IftURC0YRpiYzFFwG4OaJSBJwRFM+Y6"
+ "AQXfUx2JzZEopQQ8xxoCbvfKjNnmnSGNmBWFNvkvihun8Jq2tqjhIvJC2rsxLz9j"
+ "eiYhdNMb9rWF/65begNb9vccNf2tRM/S10+SCL4lj/MklDMo9nItnuEAPlxQsd+C"
+ "zG0kGw4q6c00ix/UfpJnr8GyrpHuUdbLDjF5qxBCqV3PapSDuEtLNrOGGqclXkwC"
+ "eLo2BGUMEL4ZSC8jFxtnHfHPO5YMB0MBzZPB0XYD0Ufa4q74N6YpZO8V5ftKrAuM"
+ "HMqkvnVKtXKK6RMMTH0CiAq5Ry1FVWIW1pmLhoIoPRnUKpDV745dMnZ9woIsbfeF"
+ "RXU4q66DBj7Zy4fC03DyY9X610ZthJnrj0ZKcCUSsM7ncekTDWl3NfiX/QNsxQQy"
+ "bDsBOZ9kNTIpD5WMC72QBl3wi6u9MK62O4TEYF1so3EEcSfQOnLVmKHtrf5wfohH"
+ "JcFokFSdaWV//////////w=="
+ "-----END X942 DH PARAMETERS-----");
+
+ config.set("dl", "modp/ietf/4096",
+ "-----BEGIN X942 DH PARAMETERS-----"
+ "MIIEDAKCAgEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb"
+ "IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft"
+ "awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT"
+ "mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh"
+ "fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq"
+ "5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM"
+ "fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq"
+ "ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI"
+ "ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O"
+ "+S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI"
+ "HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0BjGZ//////////8CAQICggIA"
+ "f//////////kh+1RELRhGmJjMUXAbg5olIEnBEUz5joBBd9THYnNkSilBDzHGgJu"
+ "98qM2eadIY2YFYU2+S+KG6fwmra2qOEi8kLauzEvP2N6JiF00xv2tYX/rlt6A1v2"
+ "9xw1/a1Ez9LXT5IIviWP8ySUMyj2ci2e4QA+XFCx34LMbSQbDirpzTSLH9R+kmev"
+ "wbKuke5R1ssOMXmrEEKpXc9qlIO4S0s2s4YapyVeTAJ4ujYEZQwQvhlILyMXG2cd"
+ "8c87lgwHQwHNk8HRdgPRR9rirvg3pilk7xXl+0qsC4wcyqS+dUq1corpEwxMfQKI"
+ "CrlHLUVVYhbWmYuGgig9GdQqkNXvjl0ydn3Cgixt94VFdTirroMGPtnLh8LTcPJj"
+ "1frXRm2EmeuPRkpwJRKwzudx6RMNaXc1+Jf9A2zFBDJsOwE5n2Q1MikPlYwLvZAG"
+ "XfCLq70wrrY7hMRgXWyjcQRxJ9A6ctWYoe2t/nB+iEclwWiQVJCEAI05HglTw/Nr"
+ "xDjNCF7dLZNM4ZOMNXpxHg1KNBpbCoXtEsH05RVqJnRt3eFtgm9HfJdHfgoP32VT"
+ "FD4so6c14C7M2Usn0Ehh0RGd0MMorfP2j7CUuGdxa9fcDe67ELgkDmgDSJPq2C1U"
+ "ydp1TEbH7uDDf9vuSFNgR6b6GuSaAxjM//////////8="
+ "-----END X942 DH PARAMETERS-----");
+
+ config.set("dl", "modp/ietf/6144",
+ "-----BEGIN X942 DH PARAMETERS-----"
+ "MIIGDAKCAwEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb"
+ "IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft"
+ "awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT"
+ "mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh"
+ "fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq"
+ "5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM"
+ "fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq"
+ "ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI"
+ "ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O"
+ "+S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI"
+ "HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0AoSSNsP6tNJ8cCbB1NyyYCZG"
+ "3sl1HnY9uje9+P+UBq2eUw7l2zgvQTABrrBqU+2QJ9gxF5cnsIZaiRjaPtvrz5sU"
+ "7UTObLrO1Lsb238UR+bMJUszIFFRK9evQm+49AE3jNK/WYPKAcZLkuzwMuoV0XId"
+ "A/SC185udP721V5wL0aYDIK1qEAxkAscnlnnyX++x+jzI6l6fjbMiL4PHUW3/1ha"
+ "xUvUB7IrQVSqzI9tfr9I4dgUzF7SD4A34KeXFe7ym+MoBqHVi7fF2nb1UKo9ih+/"
+ "8OsZzLGjE9Vc2lbJ7C7yljI4f+jXbjwEaAQ+j2Y/SGDuEr8tWwt0dNbmlPkebcxA"
+ "JP//////////AoIDAH//////////5IftURC0YRpiYzFFwG4OaJSBJwRFM+Y6AQXf"
+ "Ux2JzZEopQQ8xxoCbvfKjNnmnSGNmBWFNvkvihun8Jq2tqjhIvJC2rsxLz9jeiYh"
+ "dNMb9rWF/65begNb9vccNf2tRM/S10+SCL4lj/MklDMo9nItnuEAPlxQsd+CzG0k"
+ "Gw4q6c00ix/UfpJnr8GyrpHuUdbLDjF5qxBCqV3PapSDuEtLNrOGGqclXkwCeLo2"
+ "BGUMEL4ZSC8jFxtnHfHPO5YMB0MBzZPB0XYD0Ufa4q74N6YpZO8V5ftKrAuMHMqk"
+ "vnVKtXKK6RMMTH0CiAq5Ry1FVWIW1pmLhoIoPRnUKpDV745dMnZ9woIsbfeFRXU4"
+ "q66DBj7Zy4fC03DyY9X610ZthJnrj0ZKcCUSsM7ncekTDWl3NfiX/QNsxQQybDsB"
+ "OZ9kNTIpD5WMC72QBl3wi6u9MK62O4TEYF1so3EEcSfQOnLVmKHtrf5wfohHJcFo"
+ "kFSQhACNOR4JU8Pza8Q4zQhe3S2TTOGTjDV6cR4NSjQaWwqF7RLB9OUVaiZ0bd3h"
+ "bYJvR3yXR34KD99lUxQ+LKOnNeAuzNlLJ9BIYdERndDDKK3z9o+wlLhncWvX3A3u"
+ "uxC4JA5oA0iT6tgtVMnadUxGx+7gw3/b7khTYEem+hrkmgFCSRth/VppPjgTYOpu"
+ "WTATI29kuo87Ht0b3vx/ygNWzymHcu2cF6CYANdYNSn2yBPsGIvLk9hDLUSMbR9t"
+ "9efNinaiZzZdZ2pdje2/iiPzZhKlmZAoqJXr16E33HoAm8ZpX6zB5QDjJcl2eBl1"
+ "Cui5DoH6QWvnNzp/e2qvOBejTAZBWtQgGMgFjk8s8+S/32P0eZHUvT8bZkRfB46i"
+ "2/+sLWKl6gPZFaCqVWZHtr9fpHDsCmYvaQfAG/BTy4r3eU3xlANQ6sXb4u07eqhV"
+ "HsUP3/h1jOZY0Ynqrm0rZPYXeUsZHD/0a7ceAjQCH0ezH6Qwdwlflq2Fujprc0p8"
+ "jzbmIBJ//////////wIBAg=="
+ "-----END X942 DH PARAMETERS-----");
+
+ config.set("dl", "modp/ietf/8192",
+ "-----BEGIN X942 DH PARAMETERS-----"
+ "MIIIDAKCBAEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb"
+ "IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft"
+ "awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT"
+ "mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh"
+ "fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq"
+ "5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM"
+ "fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq"
+ "ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI"
+ "ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O"
+ "+S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI"
+ "HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0AoSSNsP6tNJ8cCbB1NyyYCZG"
+ "3sl1HnY9uje9+P+UBq2eUw7l2zgvQTABrrBqU+2QJ9gxF5cnsIZaiRjaPtvrz5sU"
+ "7UTObLrO1Lsb238UR+bMJUszIFFRK9evQm+49AE3jNK/WYPKAcZLkuzwMuoV0XId"
+ "A/SC185udP721V5wL0aYDIK1qEAxkAscnlnnyX++x+jzI6l6fjbMiL4PHUW3/1ha"
+ "xUvUB7IrQVSqzI9tfr9I4dgUzF7SD4A34KeXFe7ym+MoBqHVi7fF2nb1UKo9ih+/"
+ "8OsZzLGjE9Vc2lbJ7C7yljI4f+jXbjwEaAQ+j2Y/SGDuEr8tWwt0dNbmlPkebb4R"
+ "WXSjkm8S/uXkOHd8tqky34zYvsTQc7kxujvIMraNndMAdB+nv4r8R+0ldvaTa6Qk"
+ "ZjqrY5xa5PVoNCO0dCvxyXgjjxbL451lLeP9uL78hIrZIiIuBKQDfAcT61eoGiPw"
+ "xzRz/GRs6jBrS8vIhi+Dhd36nUt/osCH6HloMwPtW906Bis89bOieKZtKhP4P0T4"
+ "Ld8xDuB0q2o2RZfomaAlXcFk8xzFCEaFHfmrSBld7X6hsdUQvX7nTXP682vDHs+i"
+ "aDWQRvTrh5+SQAlDi0gcbNeImgAu1e44K8kZDab8Am5HlVjkR1Z36aqeMFDidlaU"
+ "38gfVuiAuW5xYMmA3Zjt09///////////wKCBAB//////////+SH7VEQtGEaYmMx"
+ "RcBuDmiUgScERTPmOgEF31Mdic2RKKUEPMcaAm73yozZ5p0hjZgVhTb5L4obp/Ca"
+ "trao4SLyQtq7MS8/Y3omIXTTG/a1hf+uW3oDW/b3HDX9rUTP0tdPkgi+JY/zJJQz"
+ "KPZyLZ7hAD5cULHfgsxtJBsOKunNNIsf1H6SZ6/Bsq6R7lHWyw4xeasQQqldz2qU"
+ "g7hLSzazhhqnJV5MAni6NgRlDBC+GUgvIxcbZx3xzzuWDAdDAc2TwdF2A9FH2uKu"
+ "+DemKWTvFeX7SqwLjBzKpL51SrVyiukTDEx9AogKuUctRVViFtaZi4aCKD0Z1CqQ"
+ "1e+OXTJ2fcKCLG33hUV1OKuugwY+2cuHwtNw8mPV+tdGbYSZ649GSnAlErDO53Hp"
+ "Ew1pdzX4l/0DbMUEMmw7ATmfZDUyKQ+VjAu9kAZd8IurvTCutjuExGBdbKNxBHEn"
+ "0Dpy1Zih7a3+cH6IRyXBaJBUkIQAjTkeCVPD82vEOM0IXt0tk0zhk4w1enEeDUo0"
+ "GlsKhe0SwfTlFWomdG3d4W2Cb0d8l0d+Cg/fZVMUPiyjpzXgLszZSyfQSGHREZ3Q"
+ "wyit8/aPsJS4Z3Fr19wN7rsQuCQOaANIk+rYLVTJ2nVMRsfu4MN/2+5IU2BHpvoa"
+ "5JoBQkkbYf1aaT44E2DqblkwEyNvZLqPOx7dG978f8oDVs8ph3LtnBegmADXWDUp"
+ "9sgT7BiLy5PYQy1EjG0fbfXnzYp2omc2XWdqXY3tv4oj82YSpZmQKKiV69ehN9x6"
+ "AJvGaV+sweUA4yXJdngZdQrouQ6B+kFr5zc6f3tqrzgXo0wGQVrUIBjIBY5PLPPk"
+ "v99j9HmR1L0/G2ZEXweOotv/rC1ipeoD2RWgqlVmR7a/X6Rw7ApmL2kHwBvwU8uK"
+ "93lN8ZQDUOrF2+LtO3qoVR7FD9/4dYzmWNGJ6q5tK2T2F3lLGRw/9Gu3HgI0Ah9H"
+ "sx+kMHcJX5athbo6a3NKfI823wisulHJN4l/cvIcO75bVJlvxmxfYmg53JjdHeQZ"
+ "W0bO6YA6D9PfxX4j9pK7e0m10hIzHVWxzi1yerQaEdo6FfjkvBHHi2XxzrKW8f7c"
+ "X35CRWyRERcCUgG+A4n1q9QNEfhjmjn+MjZ1GDWl5eRDF8HC7v1Opb/RYEP0PLQZ"
+ "gfat7p0DFZ562dE8UzaVCfwfonwW75iHcDpVtRsiy/RM0BKu4LJ5jmKEI0KO/NWk"
+ "DK72v1DY6ohev3Omuf15teGPZ9E0GsgjenXDz8kgBKHFpA42a8RNABdq9xwV5IyG"
+ "034BNyPKrHIjqzv01U8YKHE7K0pv5A+rdEBctziwZMBuzHbp7///////////AgEC"
+ "-----END X942 DH PARAMETERS-----");
+
+ config.set("dl", "dsa/jce/512",
+ "-----BEGIN DSA PARAMETERS-----"
+ "MIGdAkEA/KaCzo4Syrom78z3EQ5SbbB4sF7ey80etKII864WF64B81uRpH5t9jQT"
+ "xeEu0ImbzRMqzVDZkVG9xD7nN1kuFwIVAJYu3cw2nLqOuyYO5rahJtk0bjjFAkEA"
+ "3gtU76vylwh+5iPVylWIxkgo70/eT/uuHs0gBndrBbEbgeo83pvDlkwWh8UyW/Q9"
+ "fM76DQqGvl3/3dDRFD3NdQ=="
+ "-----END DSA PARAMETERS-----");
+
+ config.set("dl", "dsa/jce/768",
+ "-----BEGIN DSA PARAMETERS-----"
+ "MIHdAmEA6eZCWZ01XzfJf/01ZxILjiXJzUPpJ7OpZw++xdiQFBki0sOzrSSACTeZ"
+ "hp0ehGqrSfqwrSbSzmoiIZ1HC859d31KIfvpwnC1f2BwAvPO+Dk2lM9F7jaIwRqM"
+ "VqsSej2vAhUAnNvYTJ8awvOND4D0KrlS5zOL9RECYQDe7p717RUWzn5pXmcrjO5F"
+ "5s17NuDmOF+JS6hhY/bz5sbU6KgRRtQBfe/dccvZD6Akdlm4i3zByJT0gmn9Txqs"
+ "CjBTjf9rP8ds+xMcnnlltYhYqwpDtVczWRKoqlR/lWg="
+ "-----END DSA PARAMETERS-----");
+
+ config.set("dl", "dsa/jce/1024",
+ "-----BEGIN DSA PARAMETERS-----"
+ "MIIBHgKBgQD9f1OBHXUSKVLfSpwu7OTn9hG3UjzvRADDHj+AtlEmaUVdQCJR+1k9"
+ "jVj6v8X1ujD2y5tVbNeBO4AdNG/yZmC3a5lQpaSfn+gEexAiwk+7qdf+t8Yb+DtX"
+ "58aophUPBPuD9tPFHsMCNVQTWhaRMvZ1864rYdcq7/IiAxmd0UgBxwIVAJdgUI8V"
+ "IwvMspK5gqLrhAvwWBz1AoGARpYDUS4wJ4zTlHWV2yLuyYJqYyKtyXNE9B10DDJX"
+ "JMj577qn1NgD/4xgnc0QDrxb38+tfGpCX66nhuogUOvpg1HqH9of3yTWlHqmuaoj"
+ "dmlTgC9NfUqOy6BtGXaKJJH/sW0O+cQ6mbX3FnL/bwoktETQc20E04oaEyLa9s3Y"
+ "jJ0="
+ "-----END DSA PARAMETERS-----");
+
+ config.set("dl", "dsa/botan/2048",
+ "-----BEGIN DSA PARAMETERS-----"
+ "MIICLAKCAQEAkcSKT9+898Aq6V59oSYSK13Shk9Vm4fo50oobVL1m9HeaN/WRdDg"
+ "DGDAgAMYkZgDdO61lKUyv9Z7mgnqxLhmOgeRDmjzlGX7cEDSXfE5MuusQ0elMOy6"
+ "YchU+biA08DDZgCAWHxFVm2t4mvVo5S+CTtMDyS1r/747GxbPlf7iQJam8FnaZMh"
+ "MeFtPJTvyrGNDfBhIDzFPmEDvHLVWUv9QMplOA9EqahR3LB1SV/AM6ilgHGhvXj+"
+ "BS9mVVZI60txnSr+i0iA+NrW8VgYuhePiSdMhwvpuW6wjEbEAEDMLv4d+xsYaN0x"
+ "nePDSjKmOrbrEiQgmkGWgMx5AtFyjU354QIhAIzX1FD4bwrZTu5M5GmodW0evRBY"
+ "JBlD6v+ws1RYXpJNAoIBAA2fXgdhtNvRgz1qsalhoJlsXyIwP3LYTBQPZ8Qx2Uq1"
+ "cVvqgaDJjTnOS8941rnryJXTT+idlAkdWEhhXvFfXobxHZb2yWniA936WDVkIKSc"
+ "tES1lbkBqTPP4HZ7WU8YoHt/kd7NukRriJkPePL/kfL+fNQ/0uRtGOraH3u2YCxh"
+ "f27zpLKE8v2boQo2BC3o+oeiyjZZf+yBFXoUheRAQd8CgwERy4gLvm7UlIFIhvll"
+ "zcMTX1zPE4Nyi/ZbgG+WksCxDWxMCcdabKO0ATyxarLBBfa+I66pAA6rIXiYX5cs"
+ "mAV+HIbkTnIYaI6krg82NtzKdFydzU5q/7Z8y8E9YTE="
+ "-----END DSA PARAMETERS-----");
+
+ config.set("dl", "dsa/botan/3072",
+ "-----BEGIN DSA PARAMETERS-----"
+ "MIIDLAKCAYEA5LUIgHWWY1heFCRgyi2d/xMviuTIQN2jomZoiRJP5WOLhOiim3rz"
+ "+hIJvmv8S1By7Tsrc4e68/hX9HioAijvNgC3az3Pth0g00RlslBtLK+H3259wM6R"
+ "vS0Wekb2rcwxxTHk+cervbkq3fNbCoBsZikqX14X6WTdCZkDczrEKKs12A6m9oW/"
+ "uovkBo5UGK5eytno/wc94rY+Tn6tNciptwtb1Hz7iNNztm83kxk5sKtxvVWVgJCG"
+ "2gFVM30YWg5Ps2pRmxtiArhZHmACRJzxzTpmOE9tIHOxzXO+ypO68eGmEX0COPIi"
+ "rh7X/tGFqJDn9n+rj+uXU8wTSlGD3+h64llfe1wtn7tCJJ/dWVE+HTOWs+sv2GaE"
+ "8oWoRI/nV6ApiBxAdguU75Gb35dAw4OJWZ7FGm6btRmo4GhJHpzgovz+PLYNZs8N"
+ "+tIKjsaEBIaEphREV1vRck1zUrRKdgB3s71r04XOWwpyUMwL92jagpI4Buuc+7E4"
+ "hDcxthggjHWbAiEAs+vTZOxp74zzuvZDt1c0sWM5suSeXN4bWcHp+0DuDFsCggGA"
+ "K+0h7vg5ZKIwrom7px2ffDnFL8gim047x+WUTTKdoQ8BDqyee69sAJ/E6ylgcj4r"
+ "Vt9GY+TDrIAOkljeL3ZJ0gZ4KJP4Ze/KSY0u7zAHTqXop6smJxKk2UovOwuaku5A"
+ "D7OKPMWaXcfkNtXABLIuNQKDgbUck0B+sy1K4P1Cy0XhLQ7O6KJiOO3iCCp7FSIR"
+ "PGbO+NdFxs88uUX4TS9N4W1Epx3hmCcOE/A1U8iLjTI60LlIob8hA6lJl5tu0W+1"
+ "88lT2Vt8jojKZ9z1pjb7nKOdkkIV96iE7Wx+48ltjZcVQnl0t8Q1EoLhPTdz99KL"
+ "RS8QiSoTx1hzKN6kgntrNpsqjcFyrcWD9R8qZZjFSD5bxGewL5HQWcQC0Y4sJoD3"
+ "dqoG9JKAoscsF8xC1bbnQMXEsas8UcLtCSviotiwU65Xc9FCXtKwjwbi3VBZLfGk"
+ "eMFVkc39EVZP+I/zi3IdQjkv2kcyEtz9jS2IqXagCv/m//tDCjWeZMorNRyiQSOU"
+ "-----END DSA PARAMETERS-----");
+ }
+}
+
+/*************************************************
+* Set the default policy *
+*************************************************/
+void Library_State::load_default_config()
+ {
+ set_default_config(*this);
+ set_default_aliases(*this);
+ set_default_oids(*this);
+ set_default_dl_groups(*this);
+ }
+
+}
diff --git a/src/core/pubkey.cpp b/src/core/pubkey.cpp
new file mode 100644
index 000000000..06bb44bca
--- /dev/null
+++ b/src/core/pubkey.cpp
@@ -0,0 +1,415 @@
+/*************************************************
+* Public Key Base Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/pubkey.h>
+#include <botan/lookup.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/bigint.h>
+#include <botan/parsing.h>
+#include <botan/bit_ops.h>
+#include <memory>
+
+namespace Botan {
+
+/*************************************************
+* Encrypt a message *
+*************************************************/
+SecureVector<byte> PK_Encryptor::encrypt(const byte in[], u32bit len,
+ RandomNumberGenerator& rng) const
+ {
+ return enc(in, len, rng);
+ }
+
+/*************************************************
+* Encrypt a message *
+*************************************************/
+SecureVector<byte> PK_Encryptor::encrypt(const MemoryRegion<byte>& in,
+ RandomNumberGenerator& rng) const
+ {
+ return enc(in.begin(), in.size(), rng);
+ }
+
+/*************************************************
+* Decrypt a message *
+*************************************************/
+SecureVector<byte> PK_Decryptor::decrypt(const byte in[], u32bit len) const
+ {
+ return dec(in, len);
+ }
+
+/*************************************************
+* Decrypt a message *
+*************************************************/
+SecureVector<byte> PK_Decryptor::decrypt(const MemoryRegion<byte>& in) const
+ {
+ return dec(in.begin(), in.size());
+ }
+
+/*************************************************
+* PK_Encryptor_MR_with_EME Constructor *
+*************************************************/
+PK_Encryptor_MR_with_EME::PK_Encryptor_MR_with_EME(const PK_Encrypting_Key& k,
+ const std::string& eme) :
+ key(k), encoder((eme == "Raw") ? 0 : get_eme(eme))
+ {
+ }
+
+/*************************************************
+* Encrypt a message *
+*************************************************/
+SecureVector<byte>
+PK_Encryptor_MR_with_EME::enc(const byte msg[],
+ u32bit length,
+ RandomNumberGenerator& rng) const
+ {
+ SecureVector<byte> message;
+ if(encoder)
+ message = encoder->encode(msg, length, key.max_input_bits(), rng);
+ else
+ message.set(msg, length);
+
+ if(8*(message.size() - 1) + high_bit(message[0]) > key.max_input_bits())
+ throw Exception("PK_Encryptor_MR_with_EME: Input is too large");
+
+ return key.encrypt(message, message.size(), rng);
+ }
+
+/*************************************************
+* Return the max size, in bytes, of a message *
+*************************************************/
+u32bit PK_Encryptor_MR_with_EME::maximum_input_size() const
+ {
+ if(!encoder)
+ return (key.max_input_bits() / 8);
+ else
+ return encoder->maximum_input_size(key.max_input_bits());
+ }
+
+/*************************************************
+* PK_Decryptor_MR_with_EME Constructor *
+*************************************************/
+PK_Decryptor_MR_with_EME::PK_Decryptor_MR_with_EME(const PK_Decrypting_Key& k,
+ const std::string& eme) :
+ key(k), encoder((eme == "Raw") ? 0 : get_eme(eme))
+ {
+ }
+
+/*************************************************
+* Decrypt a message *
+*************************************************/
+SecureVector<byte> PK_Decryptor_MR_with_EME::dec(const byte msg[],
+ u32bit length) const
+ {
+ try {
+ SecureVector<byte> decrypted = key.decrypt(msg, length);
+ if(encoder)
+ return encoder->decode(decrypted, key.max_input_bits());
+ else
+ return decrypted;
+ }
+ catch(Invalid_Argument)
+ {
+ throw Exception("PK_Decryptor_MR_with_EME: Input is invalid");
+ }
+ catch(Decoding_Error)
+ {
+ throw Exception("PK_Decryptor_MR_with_EME: Input is invalid");
+ }
+ }
+
+/*************************************************
+* PK_Signer Constructor *
+*************************************************/
+PK_Signer::PK_Signer(const PK_Signing_Key& k, const std::string& emsa_name) :
+ key(k), emsa(get_emsa(emsa_name))
+ {
+ sig_format = IEEE_1363;
+ }
+
+/*************************************************
+* Set the signature format *
+*************************************************/
+void PK_Signer::set_output_format(Signature_Format format)
+ {
+ if(key.message_parts() == 1 && format != IEEE_1363)
+ throw Invalid_State("PK_Signer: Cannot set the output format for " +
+ key.algo_name() + " keys");
+ sig_format = format;
+ }
+
+/*************************************************
+* Sign a message *
+*************************************************/
+SecureVector<byte> PK_Signer::sign_message(const byte msg[], u32bit length,
+ RandomNumberGenerator& rng)
+ {
+ update(msg, length);
+ return signature(rng);
+ }
+
+/*************************************************
+* Sign a message *
+*************************************************/
+SecureVector<byte> PK_Signer::sign_message(const MemoryRegion<byte>& msg,
+ RandomNumberGenerator& rng)
+ {
+ return sign_message(msg, msg.size(), rng);
+ }
+
+/*************************************************
+* Add more to the message to be signed *
+*************************************************/
+void PK_Signer::update(const byte in[], u32bit length)
+ {
+ emsa->update(in, length);
+ }
+
+/*************************************************
+* Add more to the message to be signed *
+*************************************************/
+void PK_Signer::update(byte in)
+ {
+ update(&in, 1);
+ }
+
+/*************************************************
+* Add more to the message to be signed *
+*************************************************/
+void PK_Signer::update(const MemoryRegion<byte>& in)
+ {
+ update(in, in.size());
+ }
+
+/*************************************************
+* Create a signature *
+*************************************************/
+SecureVector<byte> PK_Signer::signature(RandomNumberGenerator& rng)
+ {
+ SecureVector<byte> encoded = emsa->encoding_of(emsa->raw_data(),
+ key.max_input_bits(),
+ rng);
+
+ SecureVector<byte> plain_sig = key.sign(encoded, encoded.size(), rng);
+
+ if(key.message_parts() == 1 || sig_format == IEEE_1363)
+ return plain_sig;
+
+ if(sig_format == DER_SEQUENCE)
+ {
+ if(plain_sig.size() % key.message_parts())
+ throw Encoding_Error("PK_Signer: strange signature size found");
+ const u32bit SIZE_OF_PART = plain_sig.size() / key.message_parts();
+
+ std::vector<BigInt> sig_parts(key.message_parts());
+ for(u32bit j = 0; j != sig_parts.size(); ++j)
+ sig_parts[j].binary_decode(plain_sig + SIZE_OF_PART*j, SIZE_OF_PART);
+
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode_list(sig_parts)
+ .end_cons()
+ .get_contents();
+ }
+ else
+ throw Encoding_Error("PK_Signer: Unknown signature format " +
+ to_string(sig_format));
+ }
+
+/*************************************************
+* PK_Verifier Constructor *
+*************************************************/
+PK_Verifier::PK_Verifier(const std::string& emsa_name)
+ {
+ emsa = get_emsa(emsa_name);
+ sig_format = IEEE_1363;
+ }
+
+/*************************************************
+* PK_Verifier Destructor *
+*************************************************/
+PK_Verifier::~PK_Verifier()
+ {
+ delete emsa;
+ }
+
+/*************************************************
+* Set the signature format *
+*************************************************/
+void PK_Verifier::set_input_format(Signature_Format format)
+ {
+ if(key_message_parts() == 1 && format != IEEE_1363)
+ throw Invalid_State("PK_Verifier: This algorithm always uses IEEE 1363");
+ sig_format = format;
+ }
+
+/*************************************************
+* Verify a message *
+*************************************************/
+bool PK_Verifier::verify_message(const MemoryRegion<byte>& msg,
+ const MemoryRegion<byte>& sig)
+ {
+ return verify_message(msg, msg.size(), sig, sig.size());
+ }
+
+/*************************************************
+* Verify a message *
+*************************************************/
+bool PK_Verifier::verify_message(const byte msg[], u32bit msg_length,
+ const byte sig[], u32bit sig_length)
+ {
+ update(msg, msg_length);
+ return check_signature(sig, sig_length);
+ }
+
+/*************************************************
+* Append to the message *
+*************************************************/
+void PK_Verifier::update(const byte in[], u32bit length)
+ {
+ emsa->update(in, length);
+ }
+
+/*************************************************
+* Append to the message *
+*************************************************/
+void PK_Verifier::update(byte in)
+ {
+ update(&in, 1);
+ }
+
+/*************************************************
+* Append to the message *
+*************************************************/
+void PK_Verifier::update(const MemoryRegion<byte>& in)
+ {
+ update(in, in.size());
+ }
+
+/*************************************************
+* Check a signature *
+*************************************************/
+bool PK_Verifier::check_signature(const MemoryRegion<byte>& sig)
+ {
+ return check_signature(sig, sig.size());
+ }
+
+/*************************************************
+* Check a signature *
+*************************************************/
+bool PK_Verifier::check_signature(const byte sig[], u32bit length)
+ {
+ try {
+ if(sig_format == IEEE_1363)
+ return validate_signature(emsa->raw_data(), sig, length);
+ else if(sig_format == DER_SEQUENCE)
+ {
+ BER_Decoder decoder(sig, length);
+ BER_Decoder ber_sig = decoder.start_cons(SEQUENCE);
+
+ u32bit count = 0;
+ SecureVector<byte> real_sig;
+ while(ber_sig.more_items())
+ {
+ BigInt sig_part;
+ ber_sig.decode(sig_part);
+ real_sig.append(BigInt::encode_1363(sig_part,
+ key_message_part_size()));
+ ++count;
+ }
+ if(count != key_message_parts())
+ throw Decoding_Error("PK_Verifier: signature size invalid");
+
+ return validate_signature(emsa->raw_data(),
+ real_sig, real_sig.size());
+ }
+ else
+ throw Decoding_Error("PK_Verifier: Unknown signature format " +
+ to_string(sig_format));
+ }
+ catch(Invalid_Argument) { return false; }
+ catch(Decoding_Error) { return false; }
+ }
+
+/*************************************************
+* PK_Verifier_with_MR Constructor *
+*************************************************/
+PK_Verifier_with_MR::PK_Verifier_with_MR(const PK_Verifying_with_MR_Key& k,
+ const std::string& emsa_name) :
+ PK_Verifier(emsa_name), key(k)
+ {
+ }
+
+/*************************************************
+* Verify a signature *
+*************************************************/
+bool PK_Verifier_with_MR::validate_signature(const MemoryRegion<byte>& msg,
+ const byte sig[], u32bit sig_len)
+ {
+ SecureVector<byte> output_of_key = key.verify(sig, sig_len);
+ return emsa->verify(output_of_key, msg, key.max_input_bits());
+ }
+
+/*************************************************
+* PK_Verifier_wo_MR Constructor *
+*************************************************/
+PK_Verifier_wo_MR::PK_Verifier_wo_MR(const PK_Verifying_wo_MR_Key& k,
+ const std::string& emsa_name) :
+ PK_Verifier(emsa_name), key(k)
+ {
+ }
+
+/*************************************************
+* Verify a signature *
+*************************************************/
+bool PK_Verifier_wo_MR::validate_signature(const MemoryRegion<byte>& msg,
+ const byte sig[], u32bit sig_len)
+ {
+ Null_RNG rng;
+
+ SecureVector<byte> encoded =
+ emsa->encoding_of(msg, key.max_input_bits(), rng);
+
+ return key.verify(encoded, encoded.size(), sig, sig_len);
+ }
+
+/*************************************************
+* PK_Key_Agreement Constructor *
+*************************************************/
+PK_Key_Agreement::PK_Key_Agreement(const PK_Key_Agreement_Key& k,
+ const std::string& k_name) :
+ key(k), kdf_name(k_name)
+ {
+ }
+
+/*************************************************
+* Perform Key Agreement Operation *
+*************************************************/
+SymmetricKey PK_Key_Agreement::derive_key(u32bit key_len,
+ const byte in[], u32bit in_len,
+ const std::string& params) const
+ {
+ return derive_key(key_len, in, in_len,
+ reinterpret_cast<const byte*>(params.data()),
+ params.length());
+ }
+
+/*************************************************
+* Perform Key Agreement Operation *
+*************************************************/
+SymmetricKey PK_Key_Agreement::derive_key(u32bit key_len, const byte in[],
+ u32bit in_len, const byte params[],
+ u32bit params_len) const
+ {
+ std::auto_ptr<KDF> kdf((kdf_name == "Raw") ? 0 : get_kdf(kdf_name));
+ OctetString z = key.derive_key(in, in_len);
+
+ if(kdf.get())
+ z = kdf->derive_key(key_len, z.bits_of(), params, params_len);
+
+ return z;
+ }
+
+}
diff --git a/src/core/pubkey.h b/src/core/pubkey.h
new file mode 100644
index 000000000..0c9abf18f
--- /dev/null
+++ b/src/core/pubkey.h
@@ -0,0 +1,210 @@
+/*************************************************
+* Public Key Interface Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_PUBKEY_H__
+#define BOTAN_PUBKEY_H__
+
+#include <botan/base.h>
+#include <botan/pk_keys.h>
+#include <botan/pk_util.h>
+
+namespace Botan {
+
+enum Signature_Format { IEEE_1363, DER_SEQUENCE };
+
+/*************************************************
+* Public Key Encryptor *
+*************************************************/
+class BOTAN_DLL PK_Encryptor
+ {
+ public:
+ SecureVector<byte> encrypt(const byte[], u32bit,
+ RandomNumberGenerator&) const;
+ SecureVector<byte> encrypt(const MemoryRegion<byte>&,
+ RandomNumberGenerator&) const;
+
+ virtual u32bit maximum_input_size() const = 0;
+ virtual ~PK_Encryptor() {}
+ private:
+ virtual SecureVector<byte> enc(const byte[], u32bit,
+ RandomNumberGenerator&) const = 0;
+ };
+
+/*************************************************
+* Public Key Decryptor *
+*************************************************/
+class BOTAN_DLL PK_Decryptor
+ {
+ public:
+ SecureVector<byte> decrypt(const byte[], u32bit) const;
+ SecureVector<byte> decrypt(const MemoryRegion<byte>&) const;
+ virtual ~PK_Decryptor() {}
+ private:
+ virtual SecureVector<byte> dec(const byte[], u32bit) const = 0;
+ };
+
+/*************************************************
+* Public Key Signer *
+*************************************************/
+class BOTAN_DLL PK_Signer
+ {
+ public:
+ SecureVector<byte> sign_message(const byte[], u32bit,
+ RandomNumberGenerator&);
+ SecureVector<byte> sign_message(const MemoryRegion<byte>&,
+ RandomNumberGenerator&);
+
+ void update(byte);
+ void update(const byte[], u32bit);
+ void update(const MemoryRegion<byte>&);
+
+ SecureVector<byte> signature(RandomNumberGenerator&);
+
+ void set_output_format(Signature_Format);
+
+ PK_Signer(const PK_Signing_Key&, const std::string&);
+ ~PK_Signer() { delete emsa; }
+ private:
+ PK_Signer(const PK_Signer&);
+ PK_Signer& operator=(const PK_Signer&);
+
+ const PK_Signing_Key& key;
+ Signature_Format sig_format;
+ EMSA* emsa;
+ };
+
+/*************************************************
+* Public Key Verifier *
+*************************************************/
+class BOTAN_DLL PK_Verifier
+ {
+ public:
+ bool verify_message(const byte[], u32bit, const byte[], u32bit);
+ bool verify_message(const MemoryRegion<byte>&,
+ const MemoryRegion<byte>&);
+
+ void update(byte);
+ void update(const byte[], u32bit);
+ void update(const MemoryRegion<byte>&);
+
+ bool check_signature(const byte[], u32bit);
+ bool check_signature(const MemoryRegion<byte>&);
+
+ void set_input_format(Signature_Format);
+
+ PK_Verifier(const std::string&);
+ virtual ~PK_Verifier();
+ protected:
+ virtual bool validate_signature(const MemoryRegion<byte>&,
+ const byte[], u32bit) = 0;
+ virtual u32bit key_message_parts() const = 0;
+ virtual u32bit key_message_part_size() const = 0;
+
+ Signature_Format sig_format;
+ EMSA* emsa;
+ private:
+ PK_Verifier(const PK_Verifier&);
+ PK_Verifier& operator=(const PK_Verifier&);
+ };
+
+/*************************************************
+* Key Agreement *
+*************************************************/
+class BOTAN_DLL PK_Key_Agreement
+ {
+ public:
+ SymmetricKey derive_key(u32bit, const byte[], u32bit,
+ const std::string& = "") const;
+ SymmetricKey derive_key(u32bit, const byte[], u32bit,
+ const byte[], u32bit) const;
+
+ PK_Key_Agreement(const PK_Key_Agreement_Key&, const std::string&);
+ private:
+ PK_Key_Agreement(const PK_Key_Agreement_Key&);
+ PK_Key_Agreement& operator=(const PK_Key_Agreement&);
+
+ const PK_Key_Agreement_Key& key;
+ const std::string kdf_name;
+ };
+
+/*************************************************
+* Encryption with an MR algorithm and an EME *
+*************************************************/
+class BOTAN_DLL PK_Encryptor_MR_with_EME : public PK_Encryptor
+ {
+ public:
+ u32bit maximum_input_size() const;
+
+ PK_Encryptor_MR_with_EME(const PK_Encrypting_Key&, const std::string&);
+ ~PK_Encryptor_MR_with_EME() { delete encoder; }
+
+ private:
+ PK_Encryptor_MR_with_EME(const PK_Encryptor_MR_with_EME&);
+ PK_Encryptor_MR_with_EME& operator=(const PK_Encryptor_MR_with_EME&);
+
+ SecureVector<byte> enc(const byte[], u32bit,
+ RandomNumberGenerator& rng) const;
+
+ const PK_Encrypting_Key& key;
+ const EME* encoder;
+ };
+
+/*************************************************
+* Decryption with an MR algorithm and an EME *
+*************************************************/
+class BOTAN_DLL PK_Decryptor_MR_with_EME : public PK_Decryptor
+ {
+ public:
+ PK_Decryptor_MR_with_EME(const PK_Decrypting_Key&, const std::string&);
+ ~PK_Decryptor_MR_with_EME() { delete encoder; }
+ private:
+ PK_Decryptor_MR_with_EME(const PK_Decryptor_MR_with_EME&);
+ PK_Decryptor_MR_with_EME& operator=(const PK_Decryptor_MR_with_EME&);
+
+ SecureVector<byte> dec(const byte[], u32bit) const;
+
+ const PK_Decrypting_Key& key;
+ const EME* encoder;
+ };
+
+/*************************************************
+* Public Key Verifier with Message Recovery *
+*************************************************/
+class BOTAN_DLL PK_Verifier_with_MR : public PK_Verifier
+ {
+ public:
+ PK_Verifier_with_MR(const PK_Verifying_with_MR_Key&, const std::string&);
+ private:
+ PK_Verifier_with_MR(const PK_Verifying_with_MR_Key&);
+ PK_Verifier_with_MR& operator=(const PK_Verifier_with_MR&);
+
+ bool validate_signature(const MemoryRegion<byte>&, const byte[], u32bit);
+ u32bit key_message_parts() const { return key.message_parts(); }
+ u32bit key_message_part_size() const { return key.message_part_size(); }
+
+ const PK_Verifying_with_MR_Key& key;
+ };
+
+/*************************************************
+* Public Key Verifier without Message Recovery *
+*************************************************/
+class BOTAN_DLL PK_Verifier_wo_MR : public PK_Verifier
+ {
+ public:
+ PK_Verifier_wo_MR(const PK_Verifying_wo_MR_Key&, const std::string&);
+ private:
+ PK_Verifier_wo_MR(const PK_Verifying_wo_MR_Key&);
+ PK_Verifier_wo_MR& operator=(const PK_Verifier_wo_MR&);
+
+ bool validate_signature(const MemoryRegion<byte>&, const byte[], u32bit);
+ u32bit key_message_parts() const { return key.message_parts(); }
+ u32bit key_message_part_size() const { return key.message_part_size(); }
+
+ const PK_Verifying_wo_MR_Key& key;
+ };
+
+}
+
+#endif
diff --git a/src/core/rng.cpp b/src/core/rng.cpp
new file mode 100644
index 000000000..9bed40dc1
--- /dev/null
+++ b/src/core/rng.cpp
@@ -0,0 +1,144 @@
+/*************************************************
+* Random Number Generator Base Source File *
+* (C) 1999-2008 Jack Lloyd *
+*************************************************/
+
+#include <botan/rng.h>
+#include <botan/util.h>
+#include <botan/parsing.h>
+#include <botan/timers.h>
+
+#if defined(BOTAN_HAS_RANDPOOL)
+ #include <botan/randpool.h>
+#endif
+
+#if defined(BOTAN_HAS_X931_RNG)
+ #include <botan/x931_rng.h>
+#endif
+
+#if defined(BOTAN_HAS_TIMER_HARDWARE)
+ #include <botan/tm_hard.h>
+#elif defined(BOTAN_HAS_TIMER_POSIX)
+ #include <botan/tm_posix.h>
+#elif defined(BOTAN_HAS_TIMER_UNIX)
+ #include <botan/tm_unix.h>
+#elif defined(BOTAN_HAS_TIMER_WIN32)
+ #include <botan/tm_win32.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_DEVICE)
+ #include <botan/es_dev.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_EGD)
+ #include <botan/es_egd.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_UNIX)
+ #include <botan/es_unix.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_BEOS)
+ #include <botan/es_beos.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_CAPI)
+ #include <botan/es_capi.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_WIN32)
+ #include <botan/es_win32.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_FTW)
+ #include <botan/es_ftw.h>
+#endif
+
+namespace Botan {
+
+/*************************************************
+* Default fast poll for EntropySources *
+*************************************************/
+u32bit EntropySource::fast_poll(byte buf[], u32bit len)
+ {
+ return this->slow_poll(buf, len);
+ }
+
+/*************************************************
+* Get a single random byte *
+*************************************************/
+byte RandomNumberGenerator::next_byte()
+ {
+ byte out;
+ this->randomize(&out, 1);
+ return out;
+ }
+
+/*************************************************
+* Create and seed a new RNG object *
+*************************************************/
+RandomNumberGenerator* RandomNumberGenerator::make_rng()
+ {
+ RandomNumberGenerator* rng = 0;
+
+#if defined(BOTAN_HAS_RANDPOOL)
+ rng = new Randpool("AES-256", "HMAC(SHA-256)");
+
+#if defined(BOTAN_HAS_X931_RNG)
+ rng = new ANSI_X931_RNG("AES-256", rng);
+#endif
+
+#if defined(BOTAN_HAS_TIMER_HARDWARE)
+ rng->add_entropy_source(new Hardware_Timer);
+#elif defined(BOTAN_HAS_TIMER_POSIX)
+ rng->add_entropy_source(new POSIX_Timer);
+#elif defined(BOTAN_HAS_TIMER_UNIX)
+ rng->add_entropy_source(new Unix_Timer);
+#elif defined(BOTAN_HAS_TIMER_WIN32)
+ rng->add_entropy_source(new Win32_Timer);
+#else
+ rng->add_entropy_source(new Timer);
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_DEVICE)
+ rng->add_entropy_source(
+ new Device_EntropySource(
+ split_on("/dev/random:/dev/srandom:/dev/urandom", ':')
+ )
+ );
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_EGD)
+ rng->add_entropy_source(
+ new EGD_EntropySource(split_on("/var/run/egd-pool:/dev/egd-pool", ':'))
+ );
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_CAPI)
+ rng->add_entropy_source(new Win32_CAPI_EntropySource);
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_WIN32)
+ rng->add_entropy_source(new Win32_EntropySource);
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_UNIX)
+ rng->add_entropy_source(
+ new Unix_EntropySource(split_on("/bin:/sbin:/usr/bin:/usr/sbin", ':'))
+ );
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_BEOS)
+ rng->add_entropy_source(new BeOS_EntropySource);
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_FTW)
+ rng->add_entropy_source(new FTW_EntropySource("/proc"));
+#endif
+
+#endif
+
+ return rng;
+ }
+
+}
diff --git a/src/core/rng.h b/src/core/rng.h
new file mode 100644
index 000000000..f8b9a7f62
--- /dev/null
+++ b/src/core/rng.h
@@ -0,0 +1,66 @@
+/*************************************************
+* RandomNumberGenerator Header File *
+* (C) 1999-2008 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_RANDOM_NUMBER_GENERATOR__
+#define BOTAN_RANDOM_NUMBER_GENERATOR__
+
+#include <botan/exceptn.h>
+
+namespace Botan {
+
+/*************************************************
+* Entropy Source *
+*************************************************/
+class BOTAN_DLL EntropySource
+ {
+ public:
+ virtual u32bit slow_poll(byte[], u32bit) = 0;
+ virtual u32bit fast_poll(byte[], u32bit);
+ virtual ~EntropySource() {}
+ };
+
+/*************************************************
+* Random Number Generator *
+*************************************************/
+class BOTAN_DLL RandomNumberGenerator
+ {
+ public:
+ static RandomNumberGenerator* make_rng();
+
+ virtual void randomize(byte[], u32bit) = 0;
+ virtual bool is_seeded() const = 0;
+ virtual void clear() throw() = 0;
+
+ byte next_byte();
+
+ virtual void reseed() {}
+ virtual void add_entropy_source(EntropySource*) = 0;
+ virtual void add_entropy(const byte[], u32bit) = 0;
+
+ RandomNumberGenerator() {}
+ virtual ~RandomNumberGenerator() {}
+ private:
+ RandomNumberGenerator(const RandomNumberGenerator&) {}
+ RandomNumberGenerator& operator=(const RandomNumberGenerator&)
+ { return (*this); }
+ };
+
+/*************************************************
+* Null Random Number Generator *
+*************************************************/
+class BOTAN_DLL Null_RNG : public RandomNumberGenerator
+ {
+ public:
+ void randomize(byte[], u32bit) { throw PRNG_Unseeded("Null_RNG"); }
+ void clear() throw() {};
+
+ bool is_seeded() const { return false; }
+ void add_entropy(const byte[], u32bit) {}
+ void add_entropy_source(EntropySource* es) { delete es; }
+ };
+
+}
+
+#endif
diff --git a/src/core/rsa_op.cpp b/src/core/rsa_op.cpp
new file mode 100644
index 000000000..0b151bf3b
--- /dev/null
+++ b/src/core/rsa_op.cpp
@@ -0,0 +1,83 @@
+/*************************************************
+* IF (RSA/RW) Operation Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/eng_def.h>
+#include <botan/pow_mod.h>
+#include <botan/numthry.h>
+#include <botan/reducer.h>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* Default IF Operation *
+*************************************************/
+class Default_IF_Op : public IF_Operation
+ {
+ public:
+ BigInt public_op(const BigInt& i) const
+ { return powermod_e_n(i); }
+ BigInt private_op(const BigInt&) const;
+
+ IF_Operation* clone() const { return new Default_IF_Op(*this); }
+
+ Default_IF_Op(const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&);
+ private:
+ Fixed_Exponent_Power_Mod powermod_e_n, powermod_d1_p, powermod_d2_q;
+ Modular_Reducer reducer;
+ BigInt c, q;
+ };
+
+/*************************************************
+* Default_IF_Op Constructor *
+*************************************************/
+Default_IF_Op::Default_IF_Op(const BigInt& e, const BigInt& n, const BigInt&,
+ const BigInt& p, const BigInt& q,
+ const BigInt& d1, const BigInt& d2,
+ const BigInt& c)
+ {
+ powermod_e_n = Fixed_Exponent_Power_Mod(e, n);
+
+ if(d1 != 0 && d2 != 0 && p != 0 && q != 0)
+ {
+ powermod_d1_p = Fixed_Exponent_Power_Mod(d1, p);
+ powermod_d2_q = Fixed_Exponent_Power_Mod(d2, q);
+ reducer = Modular_Reducer(p);
+ this->c = c;
+ this->q = q;
+ }
+ }
+
+/*************************************************
+* Default IF Private Operation *
+*************************************************/
+BigInt Default_IF_Op::private_op(const BigInt& i) const
+ {
+ if(q == 0)
+ throw Internal_Error("Default_IF_Op::private_op: No private key");
+
+ BigInt j1 = powermod_d1_p(i);
+ BigInt j2 = powermod_d2_q(i);
+ j1 = reducer.reduce(sub_mul(j1, j2, c));
+ return mul_add(j1, q, j2);
+ }
+
+}
+
+/*************************************************
+* Acquire an IF op *
+*************************************************/
+IF_Operation* Default_Engine::if_op(const BigInt& e, const BigInt& n,
+ const BigInt& d, const BigInt& p,
+ const BigInt& q, const BigInt& d1,
+ const BigInt& d2, const BigInt& c) const
+ {
+ return new Default_IF_Op(e, n, d, p, q, d1, d2, c);
+ }
+
+}
diff --git a/src/core/s2k.cpp b/src/core/s2k.cpp
new file mode 100644
index 000000000..9c67aef10
--- /dev/null
+++ b/src/core/s2k.cpp
@@ -0,0 +1,53 @@
+/*************************************************
+* S2K Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/s2k.h>
+
+namespace Botan {
+
+/*************************************************
+* Derive a key from a passphrase *
+*************************************************/
+OctetString S2K::derive_key(u32bit key_len,
+ const std::string& passphrase) const
+ {
+ return derive(key_len, passphrase, salt, salt.size(), iterations());
+ }
+
+/*************************************************
+* Set the number of iterations *
+*************************************************/
+void S2K::set_iterations(u32bit i)
+ {
+ iter = i;
+ }
+
+/*************************************************
+* Change the salt *
+*************************************************/
+void S2K::change_salt(const byte new_salt[], u32bit length)
+ {
+ salt.set(new_salt, length);
+ }
+
+/*************************************************
+* Change the salt *
+*************************************************/
+void S2K::change_salt(const MemoryRegion<byte>& new_salt)
+ {
+ change_salt(new_salt.begin(), new_salt.size());
+ }
+
+/*************************************************
+* Create a new random salt *
+*************************************************/
+void S2K::new_random_salt(RandomNumberGenerator& rng,
+ u32bit length)
+ {
+ salt.create(length);
+ rng.randomize(salt, length);
+ }
+
+}
diff --git a/src/core/s2k.h b/src/core/s2k.h
new file mode 100644
index 000000000..031592513
--- /dev/null
+++ b/src/core/s2k.h
@@ -0,0 +1,45 @@
+/*************************************************
+* S2K Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_S2K_H__
+#define BOTAN_S2K_H__
+
+#include <botan/symkey.h>
+#include <botan/rng.h>
+
+namespace Botan {
+
+/*************************************************
+* S2K Interface *
+*************************************************/
+class BOTAN_DLL S2K
+ {
+ public:
+ virtual S2K* clone() const = 0;
+ virtual std::string name() const = 0;
+ virtual void clear() {}
+
+ OctetString derive_key(u32bit, const std::string&) const;
+
+ void set_iterations(u32bit);
+ void change_salt(const byte[], u32bit);
+ void change_salt(const MemoryRegion<byte>&);
+ void new_random_salt(RandomNumberGenerator& rng, u32bit);
+
+ u32bit iterations() const { return iter; }
+ SecureVector<byte> current_salt() const { return salt; }
+
+ S2K() { iter = 0; }
+ virtual ~S2K() {}
+ private:
+ virtual OctetString derive(u32bit, const std::string&,
+ const byte[], u32bit, u32bit) const = 0;
+ SecureVector<byte> salt;
+ u32bit iter;
+ };
+
+}
+
+#endif
diff --git a/src/core/symkey.cpp b/src/core/symkey.cpp
new file mode 100644
index 000000000..7cc1bce64
--- /dev/null
+++ b/src/core/symkey.cpp
@@ -0,0 +1,139 @@
+/*************************************************
+* OctetString Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/symkey.h>
+#include <botan/xor_buf.h>
+#include <botan/rng.h>
+#include <botan/pipe.h>
+#include <botan/hex.h>
+#include <algorithm>
+
+namespace Botan {
+
+/*************************************************
+* Create an OctetString from RNG output *
+*************************************************/
+OctetString::OctetString(RandomNumberGenerator& rng,
+ u32bit length)
+ {
+ bits.create(length);
+ rng.randomize(bits, length);
+ }
+
+/*************************************************
+* Create an OctetString from a hex string *
+*************************************************/
+void OctetString::change(const std::string& hex_string)
+ {
+ SecureVector<byte> hex;
+ for(u32bit j = 0; j != hex_string.length(); ++j)
+ if(Hex_Decoder::is_valid(hex_string[j]))
+ hex.append(hex_string[j]);
+
+ if(hex.size() % 2 != 0)
+ throw Invalid_Argument("OctetString: hex string must encode full bytes");
+ bits.create(hex.size() / 2);
+ for(u32bit j = 0; j != bits.size(); ++j)
+ bits[j] = Hex_Decoder::decode(hex.begin() + 2*j);
+ }
+
+/*************************************************
+* Create an OctetString from a byte string *
+*************************************************/
+void OctetString::change(const byte in[], u32bit n)
+ {
+ bits.create(n);
+ bits.copy(in, n);
+ }
+
+/*************************************************
+* Set the parity of each key byte to odd *
+*************************************************/
+void OctetString::set_odd_parity()
+ {
+ const byte ODD_PARITY[256] = {
+ 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x07, 0x07, 0x08, 0x08, 0x0B, 0x0B,
+ 0x0D, 0x0D, 0x0E, 0x0E, 0x10, 0x10, 0x13, 0x13, 0x15, 0x15, 0x16, 0x16,
+ 0x19, 0x19, 0x1A, 0x1A, 0x1C, 0x1C, 0x1F, 0x1F, 0x20, 0x20, 0x23, 0x23,
+ 0x25, 0x25, 0x26, 0x26, 0x29, 0x29, 0x2A, 0x2A, 0x2C, 0x2C, 0x2F, 0x2F,
+ 0x31, 0x31, 0x32, 0x32, 0x34, 0x34, 0x37, 0x37, 0x38, 0x38, 0x3B, 0x3B,
+ 0x3D, 0x3D, 0x3E, 0x3E, 0x40, 0x40, 0x43, 0x43, 0x45, 0x45, 0x46, 0x46,
+ 0x49, 0x49, 0x4A, 0x4A, 0x4C, 0x4C, 0x4F, 0x4F, 0x51, 0x51, 0x52, 0x52,
+ 0x54, 0x54, 0x57, 0x57, 0x58, 0x58, 0x5B, 0x5B, 0x5D, 0x5D, 0x5E, 0x5E,
+ 0x61, 0x61, 0x62, 0x62, 0x64, 0x64, 0x67, 0x67, 0x68, 0x68, 0x6B, 0x6B,
+ 0x6D, 0x6D, 0x6E, 0x6E, 0x70, 0x70, 0x73, 0x73, 0x75, 0x75, 0x76, 0x76,
+ 0x79, 0x79, 0x7A, 0x7A, 0x7C, 0x7C, 0x7F, 0x7F, 0x80, 0x80, 0x83, 0x83,
+ 0x85, 0x85, 0x86, 0x86, 0x89, 0x89, 0x8A, 0x8A, 0x8C, 0x8C, 0x8F, 0x8F,
+ 0x91, 0x91, 0x92, 0x92, 0x94, 0x94, 0x97, 0x97, 0x98, 0x98, 0x9B, 0x9B,
+ 0x9D, 0x9D, 0x9E, 0x9E, 0xA1, 0xA1, 0xA2, 0xA2, 0xA4, 0xA4, 0xA7, 0xA7,
+ 0xA8, 0xA8, 0xAB, 0xAB, 0xAD, 0xAD, 0xAE, 0xAE, 0xB0, 0xB0, 0xB3, 0xB3,
+ 0xB5, 0xB5, 0xB6, 0xB6, 0xB9, 0xB9, 0xBA, 0xBA, 0xBC, 0xBC, 0xBF, 0xBF,
+ 0xC1, 0xC1, 0xC2, 0xC2, 0xC4, 0xC4, 0xC7, 0xC7, 0xC8, 0xC8, 0xCB, 0xCB,
+ 0xCD, 0xCD, 0xCE, 0xCE, 0xD0, 0xD0, 0xD3, 0xD3, 0xD5, 0xD5, 0xD6, 0xD6,
+ 0xD9, 0xD9, 0xDA, 0xDA, 0xDC, 0xDC, 0xDF, 0xDF, 0xE0, 0xE0, 0xE3, 0xE3,
+ 0xE5, 0xE5, 0xE6, 0xE6, 0xE9, 0xE9, 0xEA, 0xEA, 0xEC, 0xEC, 0xEF, 0xEF,
+ 0xF1, 0xF1, 0xF2, 0xF2, 0xF4, 0xF4, 0xF7, 0xF7, 0xF8, 0xF8, 0xFB, 0xFB,
+ 0xFD, 0xFD, 0xFE, 0xFE };
+
+ for(u32bit j = 0; j != bits.size(); ++j)
+ bits[j] = ODD_PARITY[bits[j]];
+ }
+
+/*************************************************
+* Hex encode an OctetString *
+*************************************************/
+std::string OctetString::as_string() const
+ {
+ Pipe pipe(new Hex_Encoder);
+ pipe.process_msg(bits);
+ return pipe.read_all_as_string();
+ }
+
+/*************************************************
+* XOR Operation for OctetStrings *
+*************************************************/
+OctetString& OctetString::operator^=(const OctetString& k)
+ {
+ if(&k == this) { bits.clear(); return (*this); }
+ xor_buf(bits.begin(), k.begin(), std::min(length(), k.length()));
+ return (*this);
+ }
+
+/*************************************************
+* Equality Operation for OctetStrings *
+*************************************************/
+bool operator==(const OctetString& s1, const OctetString& s2)
+ {
+ return (s1.bits_of() == s2.bits_of());
+ }
+
+/*************************************************
+* Unequality Operation for OctetStrings *
+*************************************************/
+bool operator!=(const OctetString& s1, const OctetString& s2)
+ {
+ return !(s1 == s2);
+ }
+
+/*************************************************
+* Append Operation for OctetStrings *
+*************************************************/
+OctetString operator+(const OctetString& k1, const OctetString& k2)
+ {
+ return OctetString(SecureVector<byte>(k1.bits_of(), k2.bits_of()));
+ }
+
+/*************************************************
+* XOR Operation for OctetStrings *
+*************************************************/
+OctetString operator^(const OctetString& k1, const OctetString& k2)
+ {
+ SecureVector<byte> ret(std::max(k1.length(), k2.length()));
+ ret.copy(k1.begin(), k1.length());
+ xor_buf(ret, k2.begin(), k2.length());
+ return OctetString(ret);
+ }
+
+}
diff --git a/src/core/symkey.h b/src/core/symkey.h
new file mode 100644
index 000000000..f3211eb0f
--- /dev/null
+++ b/src/core/symkey.h
@@ -0,0 +1,60 @@
+/*************************************************
+* OctetString Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_SYMKEY_H__
+#define BOTAN_SYMKEY_H__
+
+#include <botan/secmem.h>
+#include <string>
+
+namespace Botan {
+
+/*************************************************
+* Octet String *
+*************************************************/
+class BOTAN_DLL OctetString
+ {
+ public:
+ u32bit length() const { return bits.size(); }
+ SecureVector<byte> bits_of() const { return bits; }
+
+ const byte* begin() const { return bits.begin(); }
+ const byte* end() const { return bits.end(); }
+
+ std::string as_string() const;
+
+ OctetString& operator^=(const OctetString&);
+
+ void set_odd_parity();
+
+ void change(const std::string&);
+ void change(const byte[], u32bit);
+ void change(const MemoryRegion<byte>& in) { bits = in; }
+
+ OctetString(class RandomNumberGenerator&, u32bit len);
+ OctetString(const std::string& str = "") { change(str); }
+ OctetString(const byte in[], u32bit len) { change(in, len); }
+ OctetString(const MemoryRegion<byte>& in) { change(in); }
+ private:
+ SecureVector<byte> bits;
+ };
+
+/*************************************************
+* Operations on Octet Strings *
+*************************************************/
+BOTAN_DLL bool operator==(const OctetString&, const OctetString&);
+BOTAN_DLL bool operator!=(const OctetString&, const OctetString&);
+BOTAN_DLL OctetString operator+(const OctetString&, const OctetString&);
+BOTAN_DLL OctetString operator^(const OctetString&, const OctetString&);
+
+/*************************************************
+* Alternate Names *
+*************************************************/
+typedef OctetString SymmetricKey;
+typedef OctetString InitializationVector;
+
+}
+
+#endif
diff --git a/src/core/x509_key.cpp b/src/core/x509_key.cpp
new file mode 100644
index 000000000..26ce16a72
--- /dev/null
+++ b/src/core/x509_key.cpp
@@ -0,0 +1,174 @@
+/*************************************************
+* X.509 Public Key Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/x509_key.h>
+#include <botan/filters.h>
+#include <botan/asn1_obj.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/pk_algs.h>
+#include <botan/oids.h>
+#include <botan/pem.h>
+#include <memory>
+
+namespace Botan {
+
+namespace X509 {
+
+/*************************************************
+* DER or PEM encode a X.509 public key *
+*************************************************/
+void encode(const Public_Key& key, Pipe& pipe, X509_Encoding encoding)
+ {
+ std::auto_ptr<X509_Encoder> encoder(key.x509_encoder());
+ if(!encoder.get())
+ throw Encoding_Error("X509::encode: Key does not support encoding");
+
+ MemoryVector<byte> der =
+ DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(encoder->alg_id())
+ .encode(encoder->key_bits(), BIT_STRING)
+ .end_cons()
+ .get_contents();
+
+ if(encoding == PEM)
+ pipe.write(PEM_Code::encode(der, "PUBLIC KEY"));
+ else
+ pipe.write(der);
+ }
+
+/*************************************************
+* PEM encode a X.509 public key *
+*************************************************/
+std::string PEM_encode(const Public_Key& key)
+ {
+ Pipe pem;
+ pem.start_msg();
+ encode(key, pem, PEM);
+ pem.end_msg();
+ return pem.read_all_as_string();
+ }
+
+/*************************************************
+* Extract a public key and return it *
+*************************************************/
+Public_Key* load_key(DataSource& source)
+ {
+ try {
+ AlgorithmIdentifier alg_id;
+ MemoryVector<byte> key_bits;
+
+ if(ASN1::maybe_BER(source) && !PEM_Code::matches(source))
+ {
+ BER_Decoder(source)
+ .start_cons(SEQUENCE)
+ .decode(alg_id)
+ .decode(key_bits, BIT_STRING)
+ .verify_end()
+ .end_cons();
+ }
+ else
+ {
+ DataSource_Memory ber(
+ PEM_Code::decode_check_label(source, "PUBLIC KEY")
+ );
+
+ BER_Decoder(ber)
+ .start_cons(SEQUENCE)
+ .decode(alg_id)
+ .decode(key_bits, BIT_STRING)
+ .verify_end()
+ .end_cons();
+ }
+
+ if(key_bits.is_empty())
+ throw Decoding_Error("X.509 public key decoding failed");
+
+ const std::string alg_name = OIDS::lookup(alg_id.oid);
+ if(alg_name == "")
+ throw Decoding_Error("Unknown algorithm OID: " +
+ alg_id.oid.as_string());
+
+ std::auto_ptr<Public_Key> key_obj(get_public_key(alg_name));
+ if(!key_obj.get())
+ throw Decoding_Error("Unknown PK algorithm/OID: " + alg_name + ", " +
+ alg_id.oid.as_string());
+
+ std::auto_ptr<X509_Decoder> decoder(key_obj->x509_decoder());
+
+ if(!decoder.get())
+ throw Decoding_Error("Key does not support X.509 decoding");
+
+ decoder->alg_id(alg_id);
+ decoder->key_bits(key_bits);
+
+ return key_obj.release();
+ }
+ catch(Decoding_Error)
+ {
+ throw Decoding_Error("X.509 public key decoding failed");
+ }
+ }
+
+/*************************************************
+* Extract a public key and return it *
+*************************************************/
+Public_Key* load_key(const std::string& fsname)
+ {
+ DataSource_Stream source(fsname, true);
+ return X509::load_key(source);
+ }
+
+/*************************************************
+* Extract a public key and return it *
+*************************************************/
+Public_Key* load_key(const MemoryRegion<byte>& mem)
+ {
+ DataSource_Memory source(mem);
+ return X509::load_key(source);
+ }
+
+/*************************************************
+* Make a copy of this public key *
+*************************************************/
+Public_Key* copy_key(const Public_Key& key)
+ {
+ Pipe bits;
+ bits.start_msg();
+ X509::encode(key, bits, RAW_BER);
+ bits.end_msg();
+ DataSource_Memory source(bits.read_all());
+ return X509::load_key(source);
+ }
+
+/*************************************************
+* Find the allowable key constraints *
+*************************************************/
+Key_Constraints find_constraints(const Public_Key& pub_key,
+ Key_Constraints limits)
+ {
+ const Public_Key* key = &pub_key;
+ u32bit constraints = 0;
+
+ if(dynamic_cast<const PK_Encrypting_Key*>(key))
+ constraints |= KEY_ENCIPHERMENT | DATA_ENCIPHERMENT;
+
+ if(dynamic_cast<const PK_Key_Agreement_Key*>(key))
+ constraints |= KEY_AGREEMENT;
+
+ if(dynamic_cast<const PK_Verifying_wo_MR_Key*>(key) ||
+ dynamic_cast<const PK_Verifying_with_MR_Key*>(key))
+ constraints |= DIGITAL_SIGNATURE | NON_REPUDIATION;
+
+ if(limits)
+ constraints &= limits;
+
+ return Key_Constraints(constraints);
+ }
+
+}
+
+}
diff --git a/src/core/x509_key.h b/src/core/x509_key.h
new file mode 100644
index 000000000..abaeaaced
--- /dev/null
+++ b/src/core/x509_key.h
@@ -0,0 +1,58 @@
+/*************************************************
+* X.509 Public Key Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_X509_PUBLIC_KEY_H__
+#define BOTAN_X509_PUBLIC_KEY_H__
+
+#include <botan/pipe.h>
+#include <botan/pk_keys.h>
+#include <botan/alg_id.h>
+#include <botan/enums.h>
+
+namespace Botan {
+
+/*************************************************
+* X.509 Public Key Encoder *
+*************************************************/
+class BOTAN_DLL X509_Encoder
+ {
+ public:
+ virtual AlgorithmIdentifier alg_id() const = 0;
+ virtual MemoryVector<byte> key_bits() const = 0;
+ virtual ~X509_Encoder() {}
+ };
+
+/*************************************************
+* X.509 Public Key Decoder *
+*************************************************/
+class BOTAN_DLL X509_Decoder
+ {
+ public:
+ virtual void alg_id(const AlgorithmIdentifier&) = 0;
+ virtual void key_bits(const MemoryRegion<byte>&) = 0;
+ virtual ~X509_Decoder() {}
+ };
+
+namespace X509 {
+
+/*************************************************
+* X.509 Public Key Encoding/Decoding *
+*************************************************/
+BOTAN_DLL void encode(const Public_Key&, Pipe&, X509_Encoding = PEM);
+BOTAN_DLL std::string PEM_encode(const Public_Key&);
+
+BOTAN_DLL Public_Key* load_key(DataSource&);
+BOTAN_DLL Public_Key* load_key(const std::string&);
+BOTAN_DLL Public_Key* load_key(const MemoryRegion<byte>&);
+
+BOTAN_DLL Public_Key* copy_key(const Public_Key&);
+
+BOTAN_DLL Key_Constraints find_constraints(const Public_Key&, Key_Constraints);
+
+}
+
+}
+
+#endif