aboutsummaryrefslogtreecommitdiffstats
path: root/wrappers
diff options
context:
space:
mode:
Diffstat (limited to 'wrappers')
-rw-r--r--wrappers/boost-python/Makefile26
-rw-r--r--wrappers/boost-python/botan/__init__.py27
-rwxr-xr-xwrappers/boost-python/nisttest.py61
-rw-r--r--wrappers/boost-python/results.txt60
-rw-r--r--wrappers/boost-python/src/block.cpp152
-rw-r--r--wrappers/boost-python/src/common.h45
-rw-r--r--wrappers/boost-python/src/core.cpp43
-rw-r--r--wrappers/boost-python/src/filter.cpp176
-rw-r--r--wrappers/boost-python/src/hash.cpp108
-rw-r--r--wrappers/boost-python/src/macs.cpp59
-rw-r--r--wrappers/boost-python/src/pk.cpp125
-rw-r--r--wrappers/boost-python/src/stream.cpp54
-rw-r--r--wrappers/boost-python/src/x509.cpp140
-rw-r--r--wrappers/perl-xs/Botan.pm117
-rw-r--r--wrappers/perl-xs/Botan.xs829
-rw-r--r--wrappers/perl-xs/Changes4
-rw-r--r--wrappers/perl-xs/MANIFEST15
-rw-r--r--wrappers/perl-xs/Makefile.PL29
-rw-r--r--wrappers/perl-xs/data/ca.cert.derbin0 -> 712 bytes
-rw-r--r--wrappers/perl-xs/data/ca.cert.pem17
-rw-r--r--wrappers/perl-xs/t/base64.t273
-rw-r--r--wrappers/perl-xs/t/filt.t56
-rw-r--r--wrappers/perl-xs/t/hex.t256
-rw-r--r--wrappers/perl-xs/t/oid.t45
-rw-r--r--wrappers/perl-xs/t/pipe.t98
-rw-r--r--wrappers/perl-xs/t/testutl.pl26
-rw-r--r--wrappers/perl-xs/t/x509cert.t42
-rw-r--r--wrappers/perl-xs/typemap62
-rw-r--r--wrappers/swig/Makefile32
-rw-r--r--wrappers/swig/base.cpp61
-rw-r--r--wrappers/swig/base.h102
-rw-r--r--wrappers/swig/botan.swg26
-rwxr-xr-xwrappers/swig/doit.py49
-rw-r--r--wrappers/swig/filter.cpp39
-rw-r--r--wrappers/swig/pipe.cpp89
-rw-r--r--wrappers/swig/pk.swg8
-rw-r--r--wrappers/swig/readme.txt34
-rw-r--r--wrappers/swig/tests/block.py52
-rw-r--r--wrappers/swig/tests/block2.py44
-rw-r--r--wrappers/swig/tests/encrypt.py37
-rw-r--r--wrappers/swig/tests/filter.py27
-rw-r--r--wrappers/swig/tests/hash.py30
-rw-r--r--wrappers/swig/tests/mac.py12
-rw-r--r--wrappers/swig/tests/pubkey.py10
-rw-r--r--wrappers/swig/tests/stream.py17
-rw-r--r--wrappers/swig/x509.swg9
46 files changed, 3623 insertions, 0 deletions
diff --git a/wrappers/boost-python/Makefile b/wrappers/boost-python/Makefile
new file mode 100644
index 000000000..0f5ca68d2
--- /dev/null
+++ b/wrappers/boost-python/Makefile
@@ -0,0 +1,26 @@
+CXX = g++
+LANG_FLAGS = -fPIC -Wall -Wno-unused -ftemplate-depth-255
+OPT_FLAGS = -g -Os
+
+PYTHON_ROOT = /usr/lib/python2.4/config
+PYTHON_INC = -I/usr/include/python2.4
+PYTHON_DEF = -DBOOST_PYTHON_DYNAMIC_LIB -DBOOST_PYTHON_SOURCE
+
+WRAPPER_CFLAGS = $(shell botan-config --cflags)
+SHARED_CFLAGS = $(LANG_FLAGS) $(OPT_FLAGS) $(PYTHON_INC)
+
+BOOST_CFLAGS = $(PYTHON_DEF) $(SHARED_CFLAGS)
+
+WRAP_SRC = $(wildcard src/*.cpp)
+WRAP_OBJS = $(patsubst src/%.cpp,%.o,$(WRAP_SRC))
+
+all: botan/_botan.so
+
+%.o: src/%.cpp
+ $(CXX) -Isrc/ $(SHARED_CFLAGS) $(WRAPPER_CFLAGS) -c $< -o $@
+
+botan/_botan.so: $(WRAP_OBJS)
+ $(CXX) -shared -o $@ $(shell botan-config --libs) -L$(PYTHON_ROOT) $(WRAP_OBJS) -lboost_python -Wl,-rpath-link,. -Wl,-soname,$@
+
+clean:
+ rm -f $(WRAP_OBJS) botan/_botan.so botan/*.pyc
diff --git a/wrappers/boost-python/botan/__init__.py b/wrappers/boost-python/botan/__init__.py
new file mode 100644
index 000000000..9e136ed39
--- /dev/null
+++ b/wrappers/boost-python/botan/__init__.py
@@ -0,0 +1,27 @@
+from _botan import *
+
+# Initialize the library when the module is imported
+init = LibraryInitializer()
+
+class SymmetricKey(OctetString):
+ pass
+
+class InitializationVector(OctetString):
+ pass
+
+def Filter(name, key = None, iv = None, dir = None):
+ if key != None and iv != None and dir != None:
+ return make_filter(name, key, iv, dir)
+ elif key != None and dir != None:
+ return make_filter(name, key, dir)
+ elif key != None:
+ return make_filter(name, key)
+ else:
+ return make_filter(name)
+
+def Pipe(*filters):
+ pipe = PipeObj()
+ for filter in filters:
+ if filter:
+ pipe.append(filter)
+ return pipe
diff --git a/wrappers/boost-python/nisttest.py b/wrappers/boost-python/nisttest.py
new file mode 100755
index 000000000..a16ebf791
--- /dev/null
+++ b/wrappers/boost-python/nisttest.py
@@ -0,0 +1,61 @@
+#!/usr/bin/python
+
+import sys, os, botan
+from os.path import join;
+
+def validate(ca_certs, certs, crls, ee_certs):
+ store = botan.X509_Store()
+ for cert in certs:
+ if cert not in ee_certs:
+ store.add_cert(botan.X509_Certificate(cert), cert in ca_certs)
+
+ for crl in crls:
+ r = store.add_crl(botan.X509_CRL(crl))
+ if r != botan.verify_result.verified:
+ return r
+
+ for ee in ee_certs:
+ r = store.validate(botan.X509_Certificate(ee))
+ if r != botan.verify_result.verified:
+ return r
+
+ return botan.verify_result.verified
+
+def run_test(files, rootdir, testname, expected):
+ crls = [join(rootdir,x) for x in files if x.endswith(".crl")]
+ certs = [join(rootdir,x) for x in files if x.endswith(".crt")]
+ end_entity = [x for x in certs if x.find("end.crt") != -1]
+ ca_certs = [x for x in certs if x.find("root.crt") != -1]
+
+ print "%s..." % testname,
+
+ result = validate(ca_certs, certs, crls, end_entity)
+ result = repr(result).replace('botan._botan.verify_result.', '')
+
+ if result != expected:
+ print "FAILED: got %s, expected %s" % (result, expected)
+ else:
+ print "passed"
+
+def main():
+ def load_results(file):
+ results = {}
+ for line in open(file, 'r'):
+ line = line[0:line.find('#')].strip()
+ if line:
+ test,result = line.split(' ')
+ results[test] = result
+ return results
+
+ results = load_results('results.txt')
+
+ for root, dirs, files in os.walk('../nist_tests/tests'):
+ if files:
+ thistest = root[root.rfind('/')+1:]
+ if thistest in results:
+ run_test(files, root, thistest, results[thistest])
+ else:
+ print "%s... skipping - no expected result set" % thistest
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/wrappers/boost-python/results.txt b/wrappers/boost-python/results.txt
new file mode 100644
index 000000000..7a3824001
--- /dev/null
+++ b/wrappers/boost-python/results.txt
@@ -0,0 +1,60 @@
+# This is the file of expected results for nisttest.py
+test01 verified
+test02 signature_error
+test03 signature_error
+test04 verified
+test05 cert_not_yet_valid
+test06 cert_not_yet_valid
+test07 verified
+test08 cert_not_yet_valid
+test09 cert_has_expired
+test10 cert_has_expired
+test11 cert_has_expired
+test12 verified
+test13 cert_issuer_not_found
+test14 cert_issuer_not_found
+test15 verified
+test16 verified
+test17 verified
+test18 verified
+# changed; should be no_revocation_data_available, but I don't want to
+# force people to use CRLs
+test19 verified
+test20 cert_is_revoked
+test21 cert_is_revoked
+test22 ca_cert_not_for_cert_issuer
+test23 ca_cert_not_for_cert_issuer
+test24 verified
+test25 ca_cert_not_for_cert_issuer
+test26 verified
+test27 verified
+test28 ca_cert_not_for_cert_issuer
+test29 ca_cert_not_for_cert_issuer
+test30 verified
+test31 ca_cert_not_for_crl_issuer
+test32 ca_cert_not_for_crl_issuer
+test33 verified
+test54 cert_chain_too_long
+test55 cert_chain_too_long
+test56 verified
+test57 verified
+test58 cert_chain_too_long
+test59 cert_chain_too_long
+test60 cert_chain_too_long
+test61 cert_chain_too_long
+test62 verified
+test63 verified
+test64 signature_error
+# changed; I have no idea why this test is supposed to fail
+test65 verified
+test66 crl_issuer_not_found
+# changed; one of the CRLs has an unknown creator, so we fail
+# prior to getting to the end-entity check
+test67 crl_issuer_not_found
+test68 cert_is_revoked
+test69 cert_is_revoked
+test70 cert_is_revoked
+test71 cert_is_revoked
+test72 crl_has_expired
+test73 crl_has_expired
+test74 verified
diff --git a/wrappers/boost-python/src/block.cpp b/wrappers/boost-python/src/block.cpp
new file mode 100644
index 000000000..385376005
--- /dev/null
+++ b/wrappers/boost-python/src/block.cpp
@@ -0,0 +1,152 @@
+/*************************************************
+* Boost.Python module definition *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/botan.h>
+using namespace Botan;
+
+#include "common.h"
+
+class Py_BlockCipher : public BlockCipher
+ {
+ public:
+ virtual std::string enc_str(const std::string&) const = 0;
+ virtual std::string dec_str(const std::string&) const = 0;
+ virtual void set_key_obj(const OctetString&) = 0;
+
+ void clear() throw() {}
+
+ void enc(const byte in[], byte out[]) const
+ {
+ string2binary(
+ enc_str(make_string(in, BLOCK_SIZE)),
+ out, BLOCK_SIZE);
+ }
+
+ void dec(const byte in[], byte out[]) const
+ {
+ string2binary(
+ dec_str(make_string(in, BLOCK_SIZE)),
+ out, BLOCK_SIZE);
+ }
+
+ void key(const byte key[], u32bit len)
+ {
+ set_key_obj(OctetString(key, len));
+ }
+
+ Py_BlockCipher(u32bit bs, u32bit kmin, u32bit kmax, u32bit kmod) :
+ BlockCipher(bs, kmin, kmax, kmod)
+ {
+ }
+ };
+
+std::string encrypt_string(BlockCipher* cipher, const std::string& in)
+ {
+ if(in.size() != cipher->BLOCK_SIZE)
+ throw Bad_Size(in.size(), cipher->BLOCK_SIZE);
+
+ SecureVector<byte> out(cipher->BLOCK_SIZE);
+ cipher->encrypt((const byte*)in.data(), out);
+ return make_string(out);
+ }
+
+std::string decrypt_string(BlockCipher* cipher, const std::string& in)
+ {
+ if(in.size() != cipher->BLOCK_SIZE)
+ throw Bad_Size(in.size(), cipher->BLOCK_SIZE);
+
+ SecureVector<byte> out(cipher->BLOCK_SIZE);
+ cipher->decrypt((const byte*)in.data(), out);
+ return make_string(out);
+ }
+
+class Wrapped_Block_Cipher : public BlockCipher
+ {
+ public:
+ void clear() throw() { cipher->clear(); }
+
+ void enc(const byte in[], byte out[]) const { cipher->encrypt(in, out); }
+ void dec(const byte in[], byte out[]) const { cipher->decrypt(in, out); }
+ void key(const byte key[], u32bit len) { cipher->set_key(key, len); }
+ std::string name() const { return cipher->name(); }
+ BlockCipher* clone() const { return cipher->clone(); }
+
+ Wrapped_Block_Cipher(python::object py_obj, BlockCipher* c) :
+ BlockCipher(c->BLOCK_SIZE, c->MINIMUM_KEYLENGTH,
+ c->MAXIMUM_KEYLENGTH, c->KEYLENGTH_MULTIPLE),
+ obj(py_obj), cipher(c) {}
+ private:
+ python::object obj;
+ BlockCipher* cipher;
+ };
+
+class Py_BlockCipher_Wrapper : public Py_BlockCipher,
+ public python::wrapper<Py_BlockCipher>
+ {
+ public:
+ BlockCipher* clone() const
+ {
+ python::object self = get_owner(this);
+ python::object py_clone = self.attr("__class__")();
+ BlockCipher* bc = python::extract<BlockCipher*>(py_clone);
+ return new Wrapped_Block_Cipher(py_clone, bc);
+ }
+
+ void clear() throw()
+ {
+ this->get_override("clear")();
+ }
+
+ std::string name() const
+ {
+ return this->get_override("name")();
+ }
+
+ std::string enc_str(const std::string& in) const
+ {
+ return this->get_override("encrypt")(in);
+ }
+
+ std::string dec_str(const std::string& in) const
+ {
+ return this->get_override("decrypt")(in);
+ }
+
+ void set_key_obj(const OctetString& key)
+ {
+ this->get_override("set_key")(key);
+ }
+
+ Py_BlockCipher_Wrapper(u32bit bs, u32bit kmin,
+ u32bit kmax, u32bit kmod) :
+ Py_BlockCipher(bs, kmin, kmax, kmod) {}
+ };
+
+void export_block_ciphers()
+ {
+ void (BlockCipher::*set_key_ptr)(const OctetString&) =
+ &BlockCipher::set_key;
+
+ python::class_<BlockCipher, boost::noncopyable>
+ ("BlockCipher", python::no_init)
+ .def("__init__", python::make_constructor(get_block_cipher))
+ .def_readonly("block_size", &BlockCipher::BLOCK_SIZE)
+ .def_readonly("keylength_min", &BlockCipher::MINIMUM_KEYLENGTH)
+ .def_readonly("keylength_max", &BlockCipher::MAXIMUM_KEYLENGTH)
+ .def_readonly("keylength_mod", &BlockCipher::KEYLENGTH_MULTIPLE)
+ .def("valid_keylength", &BlockCipher::valid_keylength)
+ .def("name", &BlockCipher::name)
+ .def("set_key", set_key_ptr)
+ .def("encrypt", encrypt_string)
+ .def("decrypt", decrypt_string);
+
+ python::class_<Py_BlockCipher_Wrapper, python::bases<BlockCipher>,
+ boost::noncopyable>
+ ("BlockCipherImpl", python::init<u32bit, u32bit, u32bit, u32bit>())
+ .def("name", python::pure_virtual(&Py_BlockCipher::name))
+ .def("encrypt", python::pure_virtual(&Py_BlockCipher::enc_str))
+ .def("decrypt", python::pure_virtual(&Py_BlockCipher::dec_str))
+ .def("set_key", python::pure_virtual(&Py_BlockCipher::set_key_obj));
+ }
diff --git a/wrappers/boost-python/src/common.h b/wrappers/boost-python/src/common.h
new file mode 100644
index 000000000..968cc3908
--- /dev/null
+++ b/wrappers/boost-python/src/common.h
@@ -0,0 +1,45 @@
+
+#ifndef BOTAN_BOOST_PYTHON_COMMON_H__
+#define BOTAN_BOOST_PYTHON_COMMON_H__
+
+#include <botan/base.h>
+using namespace Botan;
+
+#include <boost/python.hpp>
+namespace python = boost::python;
+
+class Bad_Size : public Exception
+ {
+ public:
+ Bad_Size(u32bit got, u32bit expected) :
+ Exception("Bad size detected in Python/C++ conversion layer: got " +
+ to_string(got) + " bytes, expected " + to_string(expected))
+ {}
+ };
+
+inline std::string make_string(const byte input[], u32bit length)
+ {
+ return std::string((const char*)input, length);
+ }
+
+inline std::string make_string(const MemoryRegion<byte>& in)
+ {
+ return make_string(in.begin(), in.size());
+ }
+
+inline void string2binary(const std::string& from, byte to[], u32bit expected)
+ {
+ if(from.size() != expected)
+ throw Bad_Size(from.size(), expected);
+ std::memcpy(to, from.data(), expected);
+ }
+
+template<typename T>
+inline python::object get_owner(T* me)
+ {
+ return python::object(
+ python::handle<>(
+ python::borrowed(python::detail::wrapper_base_::get_owner(*me))));
+ }
+
+#endif
diff --git a/wrappers/boost-python/src/core.cpp b/wrappers/boost-python/src/core.cpp
new file mode 100644
index 000000000..3bca5330f
--- /dev/null
+++ b/wrappers/boost-python/src/core.cpp
@@ -0,0 +1,43 @@
+/*************************************************
+* Boost.Python module definition *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/botan.h>
+using namespace Botan;
+
+#include <boost/python.hpp>
+namespace python = boost::python;
+
+extern void export_block_ciphers();
+extern void export_stream_ciphers();
+extern void export_hash_functions();
+extern void export_macs();
+extern void export_filters();
+extern void export_pk();
+extern void export_x509();
+
+BOOST_PYTHON_MODULE(_botan)
+ {
+ python::class_<LibraryInitializer>("LibraryInitializer")
+ .def(python::init< python::optional<std::string> >());
+
+ python::class_<OctetString>("OctetString")
+ .def(python::init< python::optional<std::string> >())
+ //.def(python::init< u32bit >())
+ .def("__str__", &OctetString::as_string)
+ .def("__len__", &OctetString::length);
+
+ python::enum_<Cipher_Dir>("cipher_dir")
+ .value("encryption", ENCRYPTION)
+ .value("decryption", DECRYPTION);
+
+ export_block_ciphers();
+ export_stream_ciphers();
+ export_hash_functions();
+ export_macs();
+
+ export_filters();
+ export_pk();
+ export_x509();
+ }
diff --git a/wrappers/boost-python/src/filter.cpp b/wrappers/boost-python/src/filter.cpp
new file mode 100644
index 000000000..262622eef
--- /dev/null
+++ b/wrappers/boost-python/src/filter.cpp
@@ -0,0 +1,176 @@
+/*************************************************
+* Boost.Python module definition *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <boost/python.hpp>
+using namespace boost::python;
+
+#include <botan/pipe.h>
+#include <botan/lookup.h>
+using namespace Botan;
+
+class Py_Filter : public Filter
+ {
+ public:
+ virtual void write_str(const std::string&) = 0;
+
+ void write(const byte data[], u32bit length)
+ {
+ write_str(std::string((const char*)data, length));
+ }
+
+ void send_str(const std::string& str)
+ {
+ printf("Py_Filter::send_str\n");
+ send((const byte*)str.data(), str.length());
+ }
+ };
+
+class FilterWrapper : public Py_Filter, public wrapper<Py_Filter>
+ {
+ public:
+ void start_msg()
+ {
+ printf("wrapper start_msg\n");
+ if(override start_msg = this->get_override("start_msg"))
+ start_msg();
+ }
+
+ void end_msg()
+ {
+ printf("wrapper end_msg\n");
+ if(override end_msg = this->get_override("end_msg"))
+ end_msg();
+ }
+
+ void default_start_msg() {}
+ void default_end_msg() {}
+
+ virtual void write_str(const std::string& str)
+ {
+ printf("wrapper write\n");
+ this->get_override("write")(str);
+ }
+ };
+
+Filter* return_or_raise(Filter* filter, const std::string& name)
+ {
+ if(filter)
+ return filter;
+ throw Invalid_Argument("Filter " + name + " could not be found");
+ }
+
+Filter* make_filter1(const std::string& name)
+ {
+ Filter* filter = 0;
+
+ if(have_hash(name)) filter = new Hash_Filter(name);
+ else if(name == "Hex_Encoder") filter = new Hex_Encoder;
+ else if(name == "Hex_Decoder") filter = new Hex_Decoder;
+ else if(name == "Base64_Encoder") filter = new Base64_Encoder;
+ else if(name == "Base64_Decoder") filter = new Base64_Decoder;
+
+ return return_or_raise(filter, name);
+ }
+
+Filter* make_filter2(const std::string& name,
+ const SymmetricKey& key)
+ {
+ Filter* filter = 0;
+
+ if(have_mac(name))
+ filter = new MAC_Filter(name, key);
+ else if(have_stream_cipher(name))
+ filter = new StreamCipher_Filter(name, key);
+
+ return return_or_raise(filter, name);
+ }
+
+// FIXME: add new wrapper for Keyed_Filter here
+Filter* make_filter3(const std::string& name,
+ const SymmetricKey& key,
+ Cipher_Dir direction)
+ {
+ return return_or_raise(
+ get_cipher(global_state(), name, key, direction),
+ name);
+ }
+
+Filter* make_filter4(const std::string& name,
+ const SymmetricKey& key,
+ const InitializationVector& iv,
+ Cipher_Dir direction)
+ {
+ return return_or_raise(
+ get_cipher(global_state(), name, key, iv, direction),
+ name);
+ }
+
+void append_filter(Pipe& pipe, std::auto_ptr<Filter> filter)
+ {
+ pipe.append(filter.get());
+ filter.release();
+ }
+
+void prepend_filter(Pipe& pipe, std::auto_ptr<Filter> filter)
+ {
+ pipe.prepend(filter.get());
+ filter.release();
+ }
+
+void do_send(std::auto_ptr<FilterWrapper> filter, const std::string& data)
+ {
+ printf("Sending %s to %p\n", data.c_str(), filter.get());
+ filter->send_str(data);
+ }
+
+BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(rallas_ovls, read_all_as_string, 0, 1)
+
+void export_filters()
+ {
+ class_<Filter, std::auto_ptr<Filter>, boost::noncopyable>
+ ("__Internal_FilterObj", no_init);
+
+ def("make_filter", make_filter1,
+ return_value_policy<manage_new_object>());
+ def("make_filter", make_filter2,
+ return_value_policy<manage_new_object>());
+ def("make_filter", make_filter3,
+ return_value_policy<manage_new_object>());
+ def("make_filter", make_filter4,
+ return_value_policy<manage_new_object>());
+
+ // This might not work - Pipe will delete the filter, but Python
+ // might have allocated the space with malloc() or who-knows-what -> bad
+ class_<FilterWrapper, std::auto_ptr<FilterWrapper>,
+ bases<Filter>, boost::noncopyable>
+ ("FilterObj")
+ .def("write", pure_virtual(&Py_Filter::write_str))
+ .def("send", &do_send)
+ .def("start_msg", &Filter::start_msg, &FilterWrapper::default_start_msg)
+ .def("end_msg", &Filter::end_msg, &FilterWrapper::default_end_msg);
+
+ implicitly_convertible<std::auto_ptr<FilterWrapper>,
+ std::auto_ptr<Filter> >();
+
+ void (Pipe::*pipe_write_str)(const std::string&) = &Pipe::write;
+ void (Pipe::*pipe_process_str)(const std::string&) = &Pipe::process_msg;
+
+ class_<Pipe, boost::noncopyable>("PipeObj")
+ .def(init<>())
+ .def_readonly("LAST_MESSAGE", &Pipe::LAST_MESSAGE)
+ .def_readonly("DEFAULT_MESSAGE", &Pipe::DEFAULT_MESSAGE)
+ .add_property("default_msg", &Pipe::default_msg, &Pipe::set_default_msg)
+ .add_property("msg_count", &Pipe::message_count)
+ .def("append", append_filter)
+ .def("prepend", prepend_filter)
+ .def("reset", &Pipe::reset)
+ .def("pop", &Pipe::pop)
+ .def("end_of_data", &Pipe::end_of_data)
+ .def("start_msg", &Pipe::start_msg)
+ .def("end_msg", &Pipe::end_msg)
+ .def("write", pipe_write_str)
+ .def("process_msg", pipe_process_str)
+ .def("read_all", &Pipe::read_all_as_string, rallas_ovls());
+ }
diff --git a/wrappers/boost-python/src/hash.cpp b/wrappers/boost-python/src/hash.cpp
new file mode 100644
index 000000000..69c107c32
--- /dev/null
+++ b/wrappers/boost-python/src/hash.cpp
@@ -0,0 +1,108 @@
+/*************************************************
+* Boost.Python module definition *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/botan.h>
+using namespace Botan;
+
+#include "common.h"
+
+class Py_HashFunction : public HashFunction
+ {
+ public:
+ virtual void hash_str(const std::string&) = 0;
+ virtual std::string final_str() = 0;
+
+ void clear() throw() {}
+
+ void add_data(const byte input[], u32bit length)
+ {
+ hash_str(make_string(input, length));
+ }
+
+ void final_result(byte output[])
+ {
+ string2binary(final_str(), output, OUTPUT_LENGTH);
+ }
+
+ Py_HashFunction(u32bit digest_size, u32bit block_size) :
+ HashFunction(digest_size, block_size) {}
+ };
+
+class Wrapped_HashFunction : public HashFunction
+ {
+ public:
+ void add_data(const byte in[], u32bit len) { hash->update(in, len); }
+ void final_result(byte out[]) { hash->final(out); }
+
+ void clear() throw() {}
+
+ std::string name() const { return hash->name(); }
+ HashFunction* clone() const { return hash->clone(); }
+
+ Wrapped_HashFunction(python::object py_obj, HashFunction* h) :
+ HashFunction(h->OUTPUT_LENGTH, h->HASH_BLOCK_SIZE),
+ obj(py_obj), hash(h) {}
+ private:
+ python::object obj;
+ HashFunction* hash;
+ };
+
+class Py_HashFunction_Wrapper : public Py_HashFunction,
+ public python::wrapper<Py_HashFunction>
+ {
+ public:
+ HashFunction* clone() const
+ {
+ python::object self = get_owner(this);
+ python::object py_clone = self.attr("__class__")();
+ HashFunction* hf = python::extract<HashFunction*>(py_clone);
+ return new Wrapped_HashFunction(py_clone, hf);
+ }
+
+ std::string name() const
+ {
+ return this->get_override("name")();
+ }
+
+ void hash_str(const std::string& in)
+ {
+ this->get_override("update")(in);
+ }
+
+ std::string final_str()
+ {
+ return this->get_override("final")();
+ }
+
+ Py_HashFunction_Wrapper(u32bit digest_size, u32bit block_size) :
+ Py_HashFunction(digest_size, block_size) {}
+ };
+
+std::string final_str(HashFunction* hash)
+ {
+ SecureVector<byte> digest = hash->final();
+ return std::string((const char*)digest.begin(), digest.size());
+ }
+
+void export_hash_functions()
+ {
+ void (HashFunction::*update_str)(const std::string&) =
+ &HashFunction::update;
+
+ python::class_<HashFunction, boost::noncopyable>
+ ("HashFunction", python::no_init)
+ .def("__init__", python::make_constructor(get_hash))
+ .def_readonly("digest_size", &HashFunction::OUTPUT_LENGTH)
+ .def("name", &HashFunction::name)
+ .def("update", update_str)
+ .def("final", final_str);
+
+ python::class_<Py_HashFunction_Wrapper, python::bases<HashFunction>,
+ boost::noncopyable>
+ ("HashFunctionImpl", python::init<u32bit, u32bit>())
+ .def("name", python::pure_virtual(&Py_HashFunction::name))
+ .def("update", python::pure_virtual(&Py_HashFunction::hash_str))
+ .def("final", python::pure_virtual(&Py_HashFunction::final_str));
+ }
diff --git a/wrappers/boost-python/src/macs.cpp b/wrappers/boost-python/src/macs.cpp
new file mode 100644
index 000000000..54a55afe2
--- /dev/null
+++ b/wrappers/boost-python/src/macs.cpp
@@ -0,0 +1,59 @@
+/*************************************************
+* Boost.Python module definition *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/botan.h>
+using namespace Botan;
+
+#include <boost/python.hpp>
+namespace python = boost::python;
+
+class Py_MAC
+ {
+ public:
+ u32bit output_length() const { return mac->OUTPUT_LENGTH; }
+ u32bit keylength_min() const { return mac->MINIMUM_KEYLENGTH; }
+ u32bit keylength_max() const { return mac->MAXIMUM_KEYLENGTH; }
+ u32bit keylength_mod() const { return mac->KEYLENGTH_MULTIPLE; }
+ std::string name() const { return mac->name(); }
+ void clear() throw() { mac->clear(); }
+
+ void set_key(const OctetString& key) { mac->set_key(key); }
+
+ bool valid_keylength(u32bit kl) const
+ {
+ return mac->valid_keylength(kl);
+ }
+
+ void update(const std::string& in) { mac->update(in); }
+
+ std::string final()
+ {
+ SecureVector<byte> result = mac->final();
+ return std::string((const char*)result.begin(), result.size());
+ }
+
+ Py_MAC(const std::string& name)
+ {
+ mac = get_mac(name);
+ }
+ ~Py_MAC() { delete mac; }
+ private:
+ MessageAuthenticationCode* mac;
+ };
+
+void export_macs()
+ {
+ python::class_<Py_MAC>("MAC", python::init<std::string>())
+ .add_property("output_length", &Py_MAC::output_length)
+ .add_property("keylength_min", &Py_MAC::keylength_min)
+ .add_property("keylength_max", &Py_MAC::keylength_max)
+ .add_property("keylength_mod", &Py_MAC::keylength_mod)
+ .add_property("name", &Py_MAC::name)
+ .def("valid_keylength", &Py_MAC::valid_keylength)
+ .def("set_key", &Py_MAC::set_key)
+ .def("clear", &Py_MAC::clear)
+ .def("update", &Py_MAC::update)
+ .def("final", &Py_MAC::final);
+ }
diff --git a/wrappers/boost-python/src/pk.cpp b/wrappers/boost-python/src/pk.cpp
new file mode 100644
index 000000000..72d3294b8
--- /dev/null
+++ b/wrappers/boost-python/src/pk.cpp
@@ -0,0 +1,125 @@
+/*************************************************
+* Boost.Python module definition *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/rsa.h>
+#include <botan/dsa.h>
+#include <botan/dh.h>
+#include <botan/look_pk.h>
+using namespace Botan;
+
+#include <boost/python.hpp>
+namespace python = boost::python;
+
+std::string encode_pub(const Public_Key* key,
+ const std::string& type)
+ {
+ if(type == "DER")
+ {
+ Pipe pipe;
+ pipe.start_msg();
+ X509::encode(*key, pipe, RAW_BER);
+ pipe.end_msg();
+ return pipe.read_all_as_string();
+ }
+ else if(type == "PEM")
+ return X509::PEM_encode(*key);
+ else
+ throw Encoding_Error("Unknown key encoding method " + type);
+ }
+
+std::string encode_priv(const Private_Key* key,
+ const std::string& type)
+ {
+ if(type == "DER")
+ {
+ Pipe pipe;
+ PKCS8::encode(*key, pipe, RAW_BER);
+ return pipe.read_all_as_string();
+ }
+ else if(type == "PEM")
+ return PKCS8::PEM_encode(*key);
+ else
+ throw Encoding_Error("Unknown key encoding method " + type);
+ }
+
+/*
+Private_Key* load_priv(const std::string& file, const std::string& pass)
+ {
+ return PKCS8::load_key(file, pass);
+ }
+
+Public_Key* load_public(const std::string& file)
+ {
+ return X509::load_key(file);
+ }
+*/
+
+/*
+std::string encrypt_string(const PK_Encryptor* enc, const std::string& in)
+ {
+ SecureVector<byte> cipher = enc->encrypt((const byte*)in.data(), in.length());
+ return std::string((const char*)cipher.begin(), cipher.size());
+ }
+
+std::string decrypt_string(const PK_Decryptor* dec, const std::string& in)
+ {
+ SecureVector<byte> plain = dec->decrypt((const byte*)in.data(), in.length());
+ return std::string((const char*)plain.begin(), plain.size());
+ }
+*/
+
+void export_pk()
+ {
+ /*
+ python::def("private_key", load_priv,
+ python::return_value_policy<python::manage_new_object>());
+ python::def("public_key", load_public,
+ python::return_value_policy<python::manage_new_object>());
+ */
+
+ python::class_<Public_Key, boost::noncopyable>
+ ("Public_Key", python::no_init)
+ .add_property("name", &Public_Key::algo_name)
+ .add_property("max_input_bits", &Public_Key::max_input_bits)
+ .def("public_key", encode_pub);
+
+ python::class_<PK_Encrypting_Key, python::bases<Public_Key>, boost::noncopyable>
+ ("PK_Encrypting_Key", python::no_init);
+
+ python::class_<Private_Key, python::bases<Public_Key>, boost::noncopyable>
+ ("Private_Key", python::no_init)
+ .def("private_key", encode_priv);
+
+ python::class_<PK_Decrypting_Key, python::bases<Private_Key>, boost::noncopyable>
+ ("PK_Decrypting_Key", python::no_init);
+
+ python::class_<RSA_PublicKey, python::bases<PK_Encrypting_Key> >
+ ("RSA_PublicKey", python::no_init);
+
+ python::class_<DSA_PublicKey, python::bases<Public_Key> >
+ ("DSA_PublicKey", python::no_init);
+
+ /*
+ python::class_<RSA_PrivateKey, python::bases<RSA_PublicKey, PK_Decrypting_Key> >
+ ("RSA_PrivateKey", python::init<u32bit>());
+ */
+
+ /*
+ python::class_<PK_Encryptor, boost::noncopyable>
+ ("PK_Encryptor", python::no_init)
+ .def("__init__",
+ python::make_constructor(get_pk_encryptor,
+ python::with_custodian_and_ward_postcall<0, 1>()))
+ .def("max_input", &PK_Encryptor::maximum_input_size)
+ .def("encrypt", encrypt_string);
+ */
+
+ /*
+ python::class_<PK_Decryptor, boost::noncopyable>
+ ("PK_Decryptor", python::no_init)
+ .def("__init__", python::make_constructor(get_pk_decryptor))
+ .def("decrypt", decrypt_string);
+ */
+ }
diff --git a/wrappers/boost-python/src/stream.cpp b/wrappers/boost-python/src/stream.cpp
new file mode 100644
index 000000000..97ea9ae04
--- /dev/null
+++ b/wrappers/boost-python/src/stream.cpp
@@ -0,0 +1,54 @@
+/*************************************************
+* Boost.Python module definition *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/botan.h>
+using namespace Botan;
+
+#include "common.h"
+
+class Py_StreamCipher
+ {
+ public:
+ u32bit keylength_min() const { return cipher->MINIMUM_KEYLENGTH; }
+ u32bit keylength_max() const { return cipher->MAXIMUM_KEYLENGTH; }
+ u32bit keylength_mod() const { return cipher->KEYLENGTH_MULTIPLE; }
+
+ void set_key(const OctetString& key) { cipher->set_key(key); }
+ bool valid_keylength(u32bit kl) const
+ {
+ return cipher->valid_keylength(kl);
+ }
+
+ std::string name() const { return cipher->name(); }
+ void clear() throw() { cipher->clear(); }
+
+ std::string crypt(const std::string& in) const
+ {
+ SecureVector<byte> out(in.size());
+ cipher->encrypt((const byte*)in.data(), out.begin(), in.size());
+ return std::string((const char*)out.begin(), out.size());
+ }
+
+ Py_StreamCipher(const std::string& name)
+ {
+ cipher = get_stream_cipher(name);
+ }
+ ~Py_StreamCipher() { delete cipher; }
+ private:
+ StreamCipher* cipher;
+ };
+
+void export_stream_ciphers()
+ {
+ python::class_<Py_StreamCipher>("StreamCipher", python::init<std::string>())
+ .add_property("keylength_min", &Py_StreamCipher::keylength_min)
+ .add_property("keylength_max", &Py_StreamCipher::keylength_max)
+ .add_property("keylength_mod", &Py_StreamCipher::keylength_mod)
+ .add_property("name", &Py_StreamCipher::name)
+ .def("clear", &Py_StreamCipher::clear)
+ .def("valid_keylength", &Py_StreamCipher::valid_keylength)
+ .def("set_key", &Py_StreamCipher::set_key)
+ .def("crypt", &Py_StreamCipher::crypt);
+ }
diff --git a/wrappers/boost-python/src/x509.cpp b/wrappers/boost-python/src/x509.cpp
new file mode 100644
index 000000000..90c2bba1c
--- /dev/null
+++ b/wrappers/boost-python/src/x509.cpp
@@ -0,0 +1,140 @@
+/*************************************************
+* Boost.Python module definition *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/oids.h>
+#include <botan/pipe.h>
+#include <botan/filters.h>
+#include <botan/x509cert.h>
+#include <botan/x509_crl.h>
+#include <botan/x509stor.h>
+using namespace Botan;
+
+#include <boost/python.hpp>
+namespace python = boost::python;
+
+template<typename T>
+class vector_to_list
+ {
+ public:
+ static PyObject* convert(const std::vector<T>& in)
+ {
+ python::list out;
+ typename std::vector<T>::const_iterator i = in.begin();
+ while(i != in.end())
+ {
+ out.append(*i);
+ ++i;
+ }
+ return python::incref(out.ptr());
+ }
+
+ vector_to_list()
+ {
+ python::to_python_converter<std::vector<T>, vector_to_list<T> >();
+ }
+ };
+
+template<typename T>
+class memvec_to_hexstr
+ {
+ public:
+ static PyObject* convert(const T& in)
+ {
+ Pipe pipe(new Hex_Encoder);
+ pipe.process_msg(in);
+ std::string result = pipe.read_all_as_string();
+ return python::incref(python::str(result).ptr());
+ }
+
+ memvec_to_hexstr()
+ {
+ python::to_python_converter<T, memvec_to_hexstr<T> >();
+ }
+ };
+
+class X509_Store_Search_Wrap : public X509_Store::Search_Func,
+ public python::wrapper<X509_Store::Search_Func>
+ {
+ public:
+ bool match(const X509_Certificate& cert) const
+ {
+ return this->get_override("match")(cert);
+ }
+ };
+
+BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(add_cert_ols, add_cert, 1, 2)
+BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(validate_cert_ols, validate_cert, 1, 2)
+
+void export_x509()
+ {
+ vector_to_list<std::string>();
+ vector_to_list<X509_Certificate>();
+ memvec_to_hexstr<MemoryVector<byte> >();
+
+ python::class_<X509_Certificate>
+ ("X509_Certificate", python::init<std::string>())
+ .def(python::self == python::self)
+ .def(python::self != python::self)
+ .add_property("version", &X509_Certificate::x509_version)
+ .add_property("is_CA", &X509_Certificate::is_CA_cert)
+ .add_property("self_signed", &X509_Certificate::is_self_signed)
+ .add_property("pathlimit", &X509_Certificate::path_limit)
+ .add_property("as_pem", &X509_Object::PEM_encode)
+ .def("start_time", &X509_Certificate::start_time)
+ .def("end_time", &X509_Certificate::end_time)
+ .def("subject_info", &X509_Certificate::subject_info)
+ .def("issuer_info", &X509_Certificate::issuer_info)
+ .def("ex_constraints", &X509_Certificate::ex_constraints)
+ .def("policies", &X509_Certificate::policies)
+ .def("subject_key_id", &X509_Certificate::subject_key_id)
+ .def("authority_key_id", &X509_Certificate::authority_key_id);
+
+ python::class_<X509_CRL>
+ ("X509_CRL", python::init<std::string>())
+ .add_property("as_pem", &X509_Object::PEM_encode);
+
+ python::enum_<X509_Code>("verify_result")
+ .value("verified", VERIFIED)
+ .value("unknown_x509_error", UNKNOWN_X509_ERROR)
+ .value("cannot_establish_trust", CANNOT_ESTABLISH_TRUST)
+ .value("cert_chain_too_long", CERT_CHAIN_TOO_LONG)
+ .value("signature_error", SIGNATURE_ERROR)
+ .value("policy_error", POLICY_ERROR)
+ .value("invalid_usage", INVALID_USAGE)
+ .value("cert_format_error", CERT_FORMAT_ERROR)
+ .value("cert_issuer_not_found", CERT_ISSUER_NOT_FOUND)
+ .value("cert_not_yet_valid", CERT_NOT_YET_VALID)
+ .value("cert_has_expired", CERT_HAS_EXPIRED)
+ .value("cert_is_revoked", CERT_IS_REVOKED)
+ .value("crl_format_error", CRL_FORMAT_ERROR)
+ .value("crl_issuer_not_found", CRL_ISSUER_NOT_FOUND)
+ .value("crl_not_yet_valid", CRL_NOT_YET_VALID)
+ .value("crl_has_expired", CRL_HAS_EXPIRED)
+ .value("ca_cert_cannot_sign", CA_CERT_CANNOT_SIGN)
+ .value("ca_cert_not_for_cert_issuer", CA_CERT_NOT_FOR_CERT_ISSUER)
+ .value("ca_cert_not_for_crl_issuer", CA_CERT_NOT_FOR_CRL_ISSUER);
+
+ python::enum_<X509_Store::Cert_Usage>("cert_usage")
+ .value("any", X509_Store::ANY)
+ .value("tls_server", X509_Store::TLS_SERVER)
+ .value("tls_client", X509_Store::TLS_CLIENT)
+ .value("code_signing", X509_Store::CODE_SIGNING)
+ .value("email_protection", X509_Store::EMAIL_PROTECTION)
+ .value("time_stamping", X509_Store::TIME_STAMPING)
+ .value("crl_signing", X509_Store::CRL_SIGNING);
+
+ {
+ python::scope in_class =
+ python::class_<X509_Store>("X509_Store")
+ .def("add_cert", &X509_Store::add_cert, add_cert_ols())
+ .def("validate", &X509_Store::validate_cert, validate_cert_ols())
+ .def("get_certs", &X509_Store::get_certs)
+ .def("add_crl", &X509_Store::add_crl);
+
+ python::class_<X509_Store_Search_Wrap, boost::noncopyable>
+ ("Search_Func")
+ .def("match", python::pure_virtual(&X509_Store::Search_Func::match));
+ }
+ }
diff --git a/wrappers/perl-xs/Botan.pm b/wrappers/perl-xs/Botan.pm
new file mode 100644
index 000000000..ac4ad91fb
--- /dev/null
+++ b/wrappers/perl-xs/Botan.pm
@@ -0,0 +1,117 @@
+package Botan;
+
+use strict;
+use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $AUTOLOAD);
+
+require DynaLoader;
+require AutoLoader;
+use Carp;
+
+@ISA = qw(DynaLoader);
+$VERSION = '0.01';
+
+@EXPORT_OK = qw(
+ NONE
+ IGNORE_WS
+ FULL_CHECK
+);
+
+%EXPORT_TAGS = (
+ 'all' => [ @EXPORT_OK ],
+ 'decoder_checking' => [ qw(
+ NONE
+ IGNORE_WS
+ FULL_CHECK
+ )],
+
+);
+
+
+sub AUTOLOAD
+{
+ # This AUTOLOAD is used to 'autoload' constants from the constant()
+ # XS function. If a constant is not found then control is passed
+ # to the AUTOLOAD in AutoLoader.
+
+ my $constname = $AUTOLOAD;
+ $constname =~ s/.*:://;
+ croak '& not defined' if $constname eq 'constant';
+# my $val = constant($constname, @_ ? $_[0] : 0);
+ my $val = constant($constname);
+ if ($! != 0) {
+ if ( $! =~ /Invalid/ )
+ {
+ $AutoLoader::AUTOLOAD = $AUTOLOAD;
+ goto &AutoLoader::AUTOLOAD;
+ }
+ else
+ {
+ croak "Your vendor has not defined Botan symbol $constname";
+ }
+ }
+ no strict 'refs';
+ *$AUTOLOAD = sub { $val };
+ goto &$AUTOLOAD;
+}
+
+
+bootstrap Botan $VERSION;
+
+# to setup inheritance...
+
+package Botan::Filter;
+use vars qw(@ISA);
+@ISA = qw();
+
+package Botan::Chain;
+use vars qw(@ISA);
+@ISA = qw( Botan::Filter );
+
+package Botan::Fork;
+use vars qw(@ISA);
+@ISA = qw( Botan::Filter );
+
+package Botan::Hex_Encoder;
+use vars qw(@ISA);
+@ISA = qw( Botan::Filter );
+
+package Botan::Hex_Decoder;
+use vars qw(@ISA);
+@ISA = qw( Botan::Filter );
+
+package Botan::Base64_Decoder;
+use vars qw(@ISA);
+@ISA = qw( Botan::Filter );
+
+package Botan::Base64_Encoder;
+use vars qw(@ISA);
+@ISA = qw( Botan::Filter );
+
+
+package Botan;
+
+1;
+__END__
+
+=head1 NAME
+
+Botan - Perl extension for access to Botan ...
+
+=head1 SYNOPSIS
+
+ use Botan;
+ blah blah blah
+
+=head1 DESCRIPTION
+
+Blah blah blah.
+
+=head1 AUTHOR
+
+Vaclav Ovsik <[email protected]>
+
+=head1 SEE ALSO
+
+Bla
+
+=cut
diff --git a/wrappers/perl-xs/Botan.xs b/wrappers/perl-xs/Botan.xs
new file mode 100644
index 000000000..ded129d2e
--- /dev/null
+++ b/wrappers/perl-xs/Botan.xs
@@ -0,0 +1,829 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#include <botan/asn1_obj.h>
+#include <botan/asn1_oid.h>
+#include <botan/base64.h>
+#include <botan/basefilt.h>
+#include <botan/hex.h>
+#include <botan/init.h>
+#include <botan/oids.h>
+#include <botan/x509cert.h>
+#include <botan/x509_ext.h>
+
+
+/* xsubpp converts ':' to '_' in typemap. We create our types without ':' */
+
+typedef Botan::ASN1_String Botan__ASN1_String;
+typedef Botan::AlgorithmIdentifier Botan__AlgorithmIdentifier;
+typedef Botan::AlternativeName Botan__AlternativeName;
+typedef Botan::Attribute Botan__Attribute;
+typedef Botan::Base64_Decoder Botan__Base64_Decoder;
+typedef Botan::Base64_Encoder Botan__Base64_Encoder;
+typedef Botan::Chain Botan__Chain;
+typedef Botan::Certificate_Extension Botan__Extension;
+typedef Botan::Filter Botan__Filter;
+typedef Botan::Fork Botan__Fork;
+typedef Botan::Hex_Decoder Botan__Hex_Decoder;
+typedef Botan::Hex_Encoder Botan__Hex_Encoder;
+typedef Botan::OID Botan__OID;
+typedef Botan::Pipe Botan__Pipe;
+typedef Botan::X509_Certificate Botan__X509_Certificate;
+typedef Botan::X509_DN Botan__X509_DN;
+typedef Botan::X509_Time Botan__X509_Time;
+typedef Botan::u32bit Botan__u32bit;
+
+
+/* Types to keep track of destruction C++ objects passed
+ * into other objects...
+ * An Botan object is deleted by his parent object into which is passed,
+ * e.g. some Filter is deleted when his Pipe is destructed. We must
+ * track this and not to delete object again in Perls destructor.
+ */
+
+class ObjectInfo
+{
+private:
+ I32 d_signature;
+ bool d_del;
+public:
+ static I32 const SIGNVAL = 0x696a626f;
+ ObjectInfo() : d_signature(SIGNVAL),
+ d_del(true) {};
+ ~ObjectInfo() {};
+ void set_delete(bool del = true) { d_del = del; };
+ void set_delete_no() { set_delete(false); };
+ void set_delete_yes() { set_delete(true); };
+ bool should_delete() const { return d_del; };
+};
+
+/* Constant object in initial state - template */
+
+ObjectInfo const oi_init;
+
+
+/* Botan library initializer ... */
+
+Botan::LibraryInitializer botan_init;
+
+
+
+/*============================================================================*/
+
+MODULE = Botan PACKAGE = Botan
+
+PROTOTYPES: ENABLE
+
+void
+constant(char *name)
+ CODE:
+ using namespace Botan;
+ errno = 0;
+ switch (name[0])
+ {
+ case 'F':
+ if ( strEQ(name, "FULL_CHECK") )
+ XSRETURN_IV( FULL_CHECK ); // Decoder_Checking enum
+ break;
+ case 'I':
+ if ( strEQ(name, "IGNORE_WS") )
+ XSRETURN_IV( IGNORE_WS ); // Decoder_Checking enum
+ break;
+ case 'N':
+ if ( strEQ(name, "NONE") )
+ XSRETURN_IV( NONE ); // Decoder_Checking enum
+ break;
+ }
+ errno = EINVAL;
+ XSRETURN_UNDEF;
+
+
+# =========================== Botan::Chain ==========================
+
+MODULE = Botan PACKAGE = Botan::Chain
+
+Botan__Chain *
+Botan__Chain::new(f1 = 0, f2 = 0, f3 = 0, f4 = 0)
+ Botan__Filter *f1;
+ Botan__Filter *f2;
+ Botan__Filter *f3;
+ Botan__Filter *f4;
+ PREINIT:
+ ObjectInfo *f1_oi;
+ ObjectInfo *f2_oi;
+ ObjectInfo *f3_oi;
+ ObjectInfo *f4_oi;
+ CODE:
+ try {
+ RETVAL = new Botan__Chain(f1, f2, f3, f4);
+ if ( f1 ) f1_oi->set_delete_no();
+ if ( f2 ) f2_oi->set_delete_no();
+ if ( f3 ) f3_oi->set_delete_no();
+ if ( f4 ) f4_oi->set_delete_no();
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+void
+Botan__Chain::DESTROY()
+ PREINIT:
+ ObjectInfo *THIS_oi;
+ CODE:
+ if ( THIS_oi->should_delete() )
+ try {
+ delete THIS;
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+
+
+# =========================== Botan::Fork ==========================
+
+MODULE = Botan PACKAGE = Botan::Fork
+
+Botan__Fork *
+Botan__Fork::new(f1 = 0, f2 = 0, f3 = 0, f4 = 0)
+ Botan__Filter *f1;
+ Botan__Filter *f2;
+ Botan__Filter *f3;
+ Botan__Filter *f4;
+ PREINIT:
+ ObjectInfo *f1_oi;
+ ObjectInfo *f2_oi;
+ ObjectInfo *f3_oi;
+ ObjectInfo *f4_oi;
+ CODE:
+ try {
+ RETVAL = new Botan__Fork(f1, f2, f3, f4);
+ if ( f1 ) f1_oi->set_delete_no();
+ if ( f2 ) f2_oi->set_delete_no();
+ if ( f3 ) f3_oi->set_delete_no();
+ if ( f4 ) f4_oi->set_delete_no();
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+void
+Botan__Fork::DESTROY()
+ PREINIT:
+ ObjectInfo *THIS_oi;
+ CODE:
+ if ( THIS_oi->should_delete() )
+ try {
+ delete THIS;
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+
+
+# ============================ Botan::Base64_Decoder ============================
+
+MODULE = Botan PACKAGE = Botan::Base64_Decoder
+
+Botan__Base64_Decoder *
+Botan__Base64_Decoder::new(checking = Botan::NONE)
+ int checking;
+ CODE:
+ try {
+ using namespace Botan;
+ RETVAL = new Base64_Decoder((Decoder_Checking)checking);
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+void
+Botan__Base64_Decoder::DESTROY()
+ PREINIT:
+ ObjectInfo *THIS_oi;
+ CODE:
+ if ( THIS_oi->should_delete() )
+ try {
+ delete THIS;
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+
+
+# =========================== Botan::Base64_Encoder ==========================
+
+MODULE = Botan PACKAGE = Botan::Base64_Encoder
+
+Botan__Base64_Encoder *
+Botan__Base64_Encoder::new(breaks = false, length = 72)
+ bool breaks;
+ Botan__u32bit length;
+ CODE:
+ try {
+ RETVAL = new Botan__Base64_Encoder(breaks, length);
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+void
+Botan__Base64_Encoder::DESTROY()
+ PREINIT:
+ ObjectInfo *THIS_oi;
+ CODE:
+ if ( THIS_oi->should_delete() )
+ try {
+ delete THIS;
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+
+
+# ============================ Botan::Hex_Decoder ============================
+
+MODULE = Botan PACKAGE = Botan::Hex_Decoder
+
+Botan__Hex_Decoder *
+Botan__Hex_Decoder::new(checking = Botan::NONE)
+ int checking;
+ CODE:
+ try {
+ using namespace Botan;
+ RETVAL = new Hex_Decoder((Decoder_Checking)checking);
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+void
+Botan__Hex_Decoder::DESTROY()
+ PREINIT:
+ ObjectInfo *THIS_oi;
+ CODE:
+ if ( THIS_oi->should_delete() )
+ try {
+ delete THIS;
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+
+
+# ============================ Botan::Hex_Encoder ============================
+
+MODULE = Botan PACKAGE = Botan::Hex_Encoder
+
+Botan__Hex_Encoder *
+Botan__Hex_Encoder::new(breaks = false, length = 72, lcase = false)
+ bool breaks;
+ Botan__u32bit length;
+ bool lcase;
+ CODE:
+ try {
+ using Botan::Hex_Encoder;
+ RETVAL = new Hex_Encoder(breaks, length,
+ lcase ? Hex_Encoder::Lowercase : Hex_Encoder::Uppercase);
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+void
+Botan__Hex_Encoder::DESTROY()
+ PREINIT:
+ ObjectInfo *THIS_oi;
+ CODE:
+ if ( THIS_oi->should_delete() )
+ try {
+ delete THIS;
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+
+
+# ================================ Botan::OID ================================
+
+MODULE = Botan PACKAGE = Botan::OID
+
+Botan__OID *
+Botan__OID::new(s)
+ char *s;
+ CODE:
+ try {
+ RETVAL = new Botan__OID(s);
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+void
+Botan__OID::DESTROY()
+ CODE:
+ try {
+ delete THIS;
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+
+char *
+Botan__OID::as_string()
+ CODE:
+ try {
+ RETVAL = const_cast<char *>(THIS->as_string().c_str());
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+
+# ================================ Botan::OIDS ================================
+
+MODULE = Botan PACKAGE = Botan::OIDS
+
+void
+add_oid(oid, name)
+ Botan__OID *oid;
+ char *name;
+ CODE:
+ try {
+ Botan::OIDS::add_oid(*oid, name);
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+
+char *
+lookup_by_oid(oid)
+ Botan__OID *oid;
+ CODE:
+ try {
+ RETVAL = const_cast<char *>(Botan::OIDS::lookup(*oid).c_str());
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+Botan__OID *
+lookup_by_name(name)
+ char *name;
+ CODE:
+ try {
+ RETVAL = new Botan__OID(Botan::OIDS::lookup(name));
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ char const * CLASS = "Botan::OID";
+ OUTPUT:
+ RETVAL
+
+int
+have_oid(name)
+ char *name;
+ CODE:
+ try {
+ RETVAL = Botan::OIDS::have_oid(name);
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+
+# ================================ Botan::Pipe ================================
+
+MODULE = Botan PACKAGE = Botan::Pipe
+
+Botan__Pipe *
+Botan__Pipe::new(...)
+ CODE:
+ for (I32 i = 1; i < items; i++)
+ {
+ if ( !sv_isobject(ST(i)) || (SvTYPE(SvRV(ST(i))) != SVt_PVMG) )
+ croak("Botan::Pipe::new() -- arg %u is not "
+ "a blessed SV reference", i +1);
+ if ( !sv_derived_from(ST(i), "Botan::Filter") )
+ croak("Botan::Pipe::new() -- arg %u is not "
+ "an object derived from Botan::Filter", i +1);
+ MAGIC *mg = mg_find(SvRV(ST(i)), '~');
+ if ( mg == 0
+ || mg->mg_len != sizeof(ObjectInfo)
+ || *(I32 *)(mg->mg_ptr) != ObjectInfo::SIGNVAL )
+ croak("Botan::Pipe::new() -- arg %u has no "
+ "valid private magic data (ObjectInfo)", i +1);
+ }
+ try {
+ RETVAL = new Botan__Pipe();
+ for (I32 i = 1; i < items; i++)
+ {
+ SV *osv = (SV *)SvRV(ST(i));
+ ObjectInfo *oi = (ObjectInfo *)(mg_find(osv, '~')->mg_ptr);
+ RETVAL->append((Botan__Filter *)(SvIV(osv)));
+ oi->set_delete_no();
+ }
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+void
+Botan__Pipe::DESTROY()
+ PREINIT:
+ ObjectInfo *THIS_oi;
+ CODE:
+ try {
+ delete THIS;
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+
+void
+Botan__Pipe::write(s)
+ SV *s;
+ PREINIT:
+ ObjectInfo *THIS_oi;
+ CODE:
+ STRLEN len;
+ char *ptr = SvPV(s, len);
+ try {
+ THIS->write((unsigned char *)ptr, len);
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+
+void
+Botan__Pipe::process_msg(s)
+ SV *s;
+ PREINIT:
+ ObjectInfo *THIS_oi;
+ CODE:
+ STRLEN len;
+ char *ptr = SvPV(s, len);
+ try {
+ THIS->process_msg((unsigned char *)ptr, len);
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+
+Botan__u32bit
+Botan__Pipe::remaining(msgno = Botan::Pipe::DEFAULT_MESSAGE)
+ Botan__u32bit msgno;
+ PREINIT:
+ ObjectInfo *THIS_oi;
+ CODE:
+ try {
+ RETVAL = THIS->remaining(msgno);
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+SV *
+Botan__Pipe::read(len = 0xFFFFFFFF, msgno = Botan::Pipe::DEFAULT_MESSAGE)
+ Botan__u32bit len;
+ Botan__u32bit msgno;
+ PREINIT:
+ ObjectInfo *THIS_oi;
+ CODE:
+ try {
+ if ( len > THIS->remaining(msgno) )
+ len = THIS->remaining(msgno);
+ RETVAL = NEWSV(0, len);
+ SvPOK_on(RETVAL);
+ if ( len > 0 )
+ SvCUR_set(RETVAL, THIS->read((unsigned char *)SvPVX(RETVAL),
+ len, msgno));
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+SV *
+Botan__Pipe::peek(len = 0xFFFFFFFF, offset = 0, \
+ msgno = Botan::Pipe::DEFAULT_MESSAGE)
+ Botan__u32bit len;
+ Botan__u32bit offset;
+ Botan__u32bit msgno;
+ PREINIT:
+ ObjectInfo *THIS_oi;
+ CODE:
+ try {
+ if ( len > THIS->remaining(msgno) )
+ len = THIS->remaining(msgno);
+ RETVAL = NEWSV(0, len);
+ SvPOK_on(RETVAL);
+ if ( len > 0 )
+ SvCUR_set(RETVAL, THIS->peek((unsigned char *)SvPVX(RETVAL),
+ len, offset, msgno));
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+Botan__u32bit
+Botan__Pipe::default_msg()
+ PREINIT:
+ ObjectInfo *THIS_oi;
+ CODE:
+ try {
+ RETVAL = THIS->default_msg();
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+void
+Botan__Pipe::set_default_msg(msgno)
+ Botan__u32bit msgno;
+ PREINIT:
+ ObjectInfo *THIS_oi;
+ CODE:
+ try {
+ THIS->set_default_msg(msgno);
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+
+Botan__u32bit
+Botan__Pipe::message_count()
+ PREINIT:
+ ObjectInfo *THIS_oi;
+ CODE:
+ try {
+ RETVAL = THIS->message_count();
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+bool
+Botan__Pipe::end_of_data()
+ PREINIT:
+ ObjectInfo *THIS_oi;
+ CODE:
+ try {
+ RETVAL = THIS->end_of_data();
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+void
+Botan__Pipe::start_msg()
+ PREINIT:
+ ObjectInfo *THIS_oi;
+ CODE:
+ try {
+ THIS->start_msg();
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+
+void
+Botan__Pipe::end_msg()
+ PREINIT:
+ ObjectInfo *THIS_oi;
+ CODE:
+ try {
+ THIS->end_msg();
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+
+void
+Botan__Pipe::reset()
+ PREINIT:
+ ObjectInfo *THIS_oi;
+ CODE:
+ try {
+ THIS->reset();
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+
+
+# ========================== Botan::X509_Certificate ==========================
+
+MODULE = Botan PACKAGE = Botan::X509_Certificate
+
+Botan__X509_Certificate *
+Botan__X509_Certificate::new(char *fn)
+ CODE:
+ try {
+ RETVAL = new Botan__X509_Certificate(fn);
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+void
+Botan__X509_Certificate::DESTROY()
+ CODE:
+ try {
+ delete THIS;
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+
+unsigned int
+Botan__X509_Certificate::x509_version()
+ CODE:
+ try {
+ RETVAL = THIS->x509_version();
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+char *
+Botan__X509_Certificate::start_time()
+ CODE:
+ try {
+ RETVAL = const_cast<char *>(THIS->start_time().c_str());
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+char *
+Botan__X509_Certificate::end_time()
+ CODE:
+ try {
+ RETVAL = const_cast<char *>(THIS->end_time().c_str());
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+char *
+Botan__X509_Certificate::subject_info(char *info)
+ CODE:
+ try {
+ std::vector<std::string> s = THIS->subject_info(info);
+
+ if(s.size() > 0)
+ RETVAL = const_cast<char *>(s[0].c_str());
+ else
+ RETVAL = "err";
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+char *
+Botan__X509_Certificate::issuer_info(char *info)
+ CODE:
+ try {
+ std::vector<std::string> s = THIS->subject_info(info);
+
+ if(s.size() > 0)
+ RETVAL = const_cast<char *>(s[0].c_str());
+ else
+ RETVAL = "err";
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+Botan__X509_DN *
+Botan__X509_Certificate::subject_dn()
+ CODE:
+ try {
+ RETVAL = new Botan__X509_DN(THIS->subject_dn());
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ char const * CLASS = "Botan::X509_DN";
+ OUTPUT:
+ RETVAL
+
+Botan__X509_DN *
+Botan__X509_Certificate::issuer_dn()
+ CODE:
+ try {
+ RETVAL = new Botan__X509_DN(THIS->issuer_dn());
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ char const * CLASS = "Botan::X509_DN";
+ OUTPUT:
+ RETVAL
+
+
+# ============================== Botan::X509_DN ==============================
+
+MODULE = Botan PACKAGE = Botan::X509_DN
+
+Botan__X509_DN *
+Botan__X509_DN::new()
+ CODE:
+ try {
+ RETVAL = new Botan__X509_DN();
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+void
+Botan__X509_DN::DESTROY()
+ CODE:
+ try {
+ delete THIS;
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+
+AV *
+Botan__X509_DN::get_attributes()
+ CODE:
+ try {
+ using namespace std;
+ using namespace Botan;
+
+ typedef multimap<OID, string>::const_iterator rdn_iter;
+
+ multimap<OID, string> const &atrmmap = THIS->get_attributes();
+ RETVAL = newAV();
+ for(rdn_iter i = atrmmap.begin(); i != atrmmap.end(); i++)
+ {
+ string const &atr = i->first.as_string();
+ string const &val = i->second;
+ av_push(RETVAL, newSVpvn(atr.c_str(), atr.length()));
+ av_push(RETVAL, newSVpvn(val.c_str(), val.length()));
+ }
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
diff --git a/wrappers/perl-xs/Changes b/wrappers/perl-xs/Changes
new file mode 100644
index 000000000..5f32b0c63
--- /dev/null
+++ b/wrappers/perl-xs/Changes
@@ -0,0 +1,4 @@
+Revision history for Perl extension to Botan.
+
+0.01 Fri, 20 Feb 2004 15:10:50 +0100
+ - first version
diff --git a/wrappers/perl-xs/MANIFEST b/wrappers/perl-xs/MANIFEST
new file mode 100644
index 000000000..b9d8454d6
--- /dev/null
+++ b/wrappers/perl-xs/MANIFEST
@@ -0,0 +1,15 @@
+Botan.pm
+Botan.xs
+Changes
+MANIFEST
+Makefile.PL
+data/ca.cert.der
+data/ca.cert.pem
+t/base64.t
+t/filt.t
+t/hex.t
+t/oid.t
+t/pipe.t
+t/testutl.pl
+t/x509cert.t
+typemap
diff --git a/wrappers/perl-xs/Makefile.PL b/wrappers/perl-xs/Makefile.PL
new file mode 100644
index 000000000..d35c99168
--- /dev/null
+++ b/wrappers/perl-xs/Makefile.PL
@@ -0,0 +1,29 @@
+use ExtUtils::MakeMaker;
+
+my ($cc, $cflags, $lids);
+if ( $^O eq 'MSWin32' )
+{
+# $cflags = '';
+# $libs = ':nosearch -lgdi32 -llibeay32';
+}
+else
+{
+ $cc = 'g++';
+ $cflags = '-fexceptions ' . qx( botan-config --cflags );
+ $libs = qx( botan-config --libs );
+}
+
+WriteMakefile(
+ 'NAME' => 'Botan',
+ 'DISTNAME' => 'Botan-XS',
+ 'VERSION_FROM' => 'Botan.pm', # finds $VERSION
+ 'XSOPT' => '-C++',
+ 'CC' => $cc,
+ 'LD' => '$(CC)',
+ 'CCFLAGS' => $cflags,
+ 'LIBS' => [ $libs ],
+ 'OPTIMIZE' => '-g',
+# 'clean' => {
+# 'FILES' => 'neco.p12 rnd',
+# },
+);
diff --git a/wrappers/perl-xs/data/ca.cert.der b/wrappers/perl-xs/data/ca.cert.der
new file mode 100644
index 000000000..d6ed8aeaf
--- /dev/null
+++ b/wrappers/perl-xs/data/ca.cert.der
Binary files differ
diff --git a/wrappers/perl-xs/data/ca.cert.pem b/wrappers/perl-xs/data/ca.cert.pem
new file mode 100644
index 000000000..012913b26
--- /dev/null
+++ b/wrappers/perl-xs/data/ca.cert.pem
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICxDCCAi2gAwIBAgIBEjANBgkqhkiG9w0BAQUFADBSMQswCQYDVQQGEwJDWjER
+MA8GA1UEChMISUNaIGEucy4xGDAWBgNVBAMTD1Rlc3QgcHJpbWFyeSBDQTEWMBQG
+CSqGSIb3DQEJARYHY2FAaS5jejAeFw0wMDA4MjAyMTQ4MDBaFw0wMjA4MTAyMTQ4
+MDBaME8xCzAJBgNVBAYTAkNaMREwDwYDVQQKEwhJQ1ogYS5zLjEVMBMGA1UEAxMM
+VGVzdCBzaWduIENBMRYwFAYJKoZIhvcNAQkBFgdjYUBpLmN6MIGfMA0GCSqGSIb3
+DQEBAQUAA4GNADCBiQKBgQCo2GReNqwU0/8bZZua5hgYaVHvD9QAmfILNXD25jRk
+C8lqe5m/GzbmftSUso5HyUy1t+qzvRDTmxK8uRn0P00Mqj9gjwF8PGQvZE/FrDF7
+rta9GCcH4n2GfQ0iexlhRZW44AfOD4HCgq38Z0bzBclsvUslBWe1AT+S5+chZ5Wb
+UwIDAQABo4GsMIGpMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFLXqc1b1DOfGehii
+k4Z+/ih9BYZmMHoGA1UdIwRzMHGAFL7x2ToS4RDAbDJu4fHnzzGjfGmgoVakVDBS
+MQswCQYDVQQGEwJDWjERMA8GA1UEChMISUNaIGEucy4xGDAWBgNVBAMTD1Rlc3Qg
+cHJpbWFyeSBDQTEWMBQGCSqGSIb3DQEJARYHY2FAaS5jeoIBADANBgkqhkiG9w0B
+AQUFAAOBgQAKD9ku9kKXUGhSw8KuWJXTnEsIUzDtgmREBEUOtEvGfU45vogWN7ZL
+9fQZ1deywN4RJ4T5ZTTcCTPodOdG+IXLJ+uPn/m9iQ/D86c3GKS3yx4JNAn5PH1m
+qLsMYVjbFD2uREZQsqbg3RT6L1D8+oK0pN379u3bD6oJx/qa7+F4Jg==
+-----END CERTIFICATE-----
diff --git a/wrappers/perl-xs/t/base64.t b/wrappers/perl-xs/t/base64.t
new file mode 100644
index 000000000..f0973e13e
--- /dev/null
+++ b/wrappers/perl-xs/t/base64.t
@@ -0,0 +1,273 @@
+# vim: set ft=perl:
+# Before `make install' is performed this script should be runnable with
+# `make test'. After `make install' it should work as `perl test.pl'
+
+######################### We start with some black magic to print on failure.
+
+# Change 1..1 below to 1..last_test_to_print .
+# (It may become useful if the test is moved to ./t subdirectory.)
+
+BEGIN { $| = 1; print "1..24\n"; }
+END { print "not ok 1\n" unless $loaded; }
+
+require 't/testutl.pl';
+use Botan;
+
+$loaded = 1;
+print "ok 1\n";
+
+######################### End of black magic.
+
+# Insert your test code below (better if it prints "ok 13"
+# (correspondingly "not ok 13") depending on the success of chunk 13
+# of the test code):
+
+use strict;
+
+# Data prep
+
+my $botan_lic_b64_garbage = <<'EOF';
+Q29weXJpZ2h0IChDKSAxOTk5LTIwMDQgVGhlIEJvdGFuIFByb2plY3QuIEFsbCBy__�
+aWdodHMgcmVzZXJ2ZWQuCgpSZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJj$$*:
+ZSBhbmQgYmluYXJ5IGZvcm1zLCBmb3IgYW55IHVzZSwgd2l0aCBvciB3aXRob3V0!@#$%^&*(
+Cm1vZGlmaWNhdGlvbiwgaXMgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQgdGhlIGZv[\]
+bGxvd2luZyBjb25kaXRpb25zIGFyZSBtZXQ6CgoxLiBSZWRpc3RyaWJ1dGlvbnMg'~`
+b2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodCBu()
+b3RpY2UsIHRoaXMKbGlzdCBvZiBjb25kaXRpb25zLCBhbmQgdGhlIGZvbGxvd2lu
+ZyBkaXNjbGFpbWVyLgoKMi4gUmVkaXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3Jt
+IG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLAp0aGlz
+IGxpc3Qgb2YgY29uZGl0aW9ucywgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1l
+ciBpbiB0aGUgZG9jdW1lbnRhdGlvbgphbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHBy_,^
+b3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi4KClRISVMgU09GVFdBUkUgSVMg{|}~~~~~
+UFJPVklERUQgQlkgVEhFIEFVVEhPUihTKSAiQVMgSVMiIEFORCBBTlkgRVhQUkVT~~~~~~~~
+UyBPUiBJTVBMSUVECldBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVCBMSU1J__:;
+VEVEIFRPLCBUSEUgSU1QTElFRCBXQVJSQU5USUVTIE9GCk1FUkNIQU5UQUJJTElU
+WSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UsIEFSRSBESVND
+TEFJTUVELgoKSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUihTKSBPUiBDT05U
+UklCVVRPUihTKSBCRSBMSUFCTEUgRk9SIEFOWSBESVJFQ1QsCklORElSRUNULCBJ
+TkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwg
+REFNQUdFUyAoSU5DTFVESU5HLApCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVN
+RU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1IgU0VSVklDRVM7IExPU1MgT0YgVVNF
+LApEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pIEhP
+V0VWRVIgQ0FVU0VEIEFORCBPTiBBTlkgVEhFT1JZIE9GCkxJQUJJTElUWSwgV0hF
+VEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVCAoSU5D
+TFVESU5HIE5FR0xJR0VOQ0UKT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOIEFOWSBX
+QVkgT1VUIE9GIFRIRSBVU0UgT0YgVEhJUyBTT0ZUV0FSRSwgRVZFTiBJRgpBRFZJ
+U0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS4K
+EOF
+
+my $botan_lic_b64_ws = $botan_lic_b64_garbage;
+$botan_lic_b64_ws =~ s/[^A-Za-z0-9+\/= \n]//g;
+
+my $botan_lic_b64 = $botan_lic_b64_ws;
+$botan_lic_b64 =~ s/[ \n]//g;
+
+
+my $botan_lic = <<'EOF';
+Copyright (C) 1999-2004 The Botan Project. All rights reserved.
+
+Redistribution and use in source and binary forms, for any use, with or without
+modification, is permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions, and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions, and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
+
+IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTOR(S) BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+EOF
+
+
+# Decoder...
+
+my $f;
+
+eval { $f = Botan::Base64_Decoder->new(&Botan::NONE); };
+print "not " if $@ || !defined $f;
+print "ok 2\n";
+
+my $dec;
+eval { $dec = Botan::Pipe->new($f); };
+print "not " if $@ || !defined $dec;
+print "ok 3\n";
+
+eval { $f = Botan::Base64_Decoder->new(&Botan::IGNORE_WS); };
+print "not " if $@ || !defined $f;
+print "ok 4\n";
+
+my $dec_is;
+eval { $dec_is = Botan::Pipe->new($f); };
+print "not " if $@ || !defined $dec_is;
+print "ok 5\n";
+
+eval { $f = Botan::Base64_Decoder->new(&Botan::FULL_CHECK); };
+print "not " if $@ || !defined $f;
+print "ok 6\n";
+
+my $dec_fc;
+eval { $dec_fc = Botan::Pipe->new($f); };
+print "not " if $@ || !defined $dec_fc;
+print "ok 7\n";
+
+
+# Testing clean base64 input
+
+my $data;
+
+undef $data;
+eval {
+ $dec->process_msg($botan_lic_b64);
+ $data = $dec->read();
+};
+
+print "not " if $@ || $data ne $botan_lic;
+print "ok 8\n";
+
+undef $data;
+eval {
+ $dec_is->process_msg($botan_lic_b64);
+ $data = $dec_is->read();
+};
+
+print "not " if $@ || $data ne $botan_lic;
+print "ok 9\n";
+
+undef $data;
+eval {
+ $dec_fc->process_msg($botan_lic_b64);
+ $data = $dec_fc->read();
+};
+
+print "not " if $@ || $data ne $botan_lic;
+print "ok 10\n";
+
+
+# Testing base64 input with whitespaces
+
+undef $data;
+eval {
+ $dec->process_msg($botan_lic_b64_ws);
+ $dec->set_default_msg(1);
+ $data = $dec->read();
+};
+
+print "not " if $@ || $data ne $botan_lic;
+print "ok 11\n";
+
+undef $data;
+eval {
+ $dec_is->process_msg($botan_lic_b64_ws);
+ $dec_is->set_default_msg(1);
+ $data = $dec_is->read();
+};
+
+print "not " if $@ || $data ne $botan_lic;
+print "ok 12\n";
+
+undef $data;
+eval {
+ $dec_fc->process_msg($botan_lic_b64_ws);
+ $dec_fc->set_default_msg(1);
+ $data = $dec_fc->read();
+};
+
+print "not " unless $@ && !defined $data;
+print "ok 13\n";
+
+
+# Testing base64 input with garbage
+
+undef $data;
+eval {
+ $dec->process_msg($botan_lic_b64_garbage);
+ $dec->set_default_msg(2);
+ $data = $dec->read();
+};
+
+print "not " if $@ || $data ne $botan_lic;
+print "ok 14\n";
+
+undef $data;
+eval {
+ $dec_is->process_msg($botan_lic_b64_garbage);
+ $dec_is->set_default_msg(2);
+ $data = $dec_is->read();
+};
+
+print "not " unless $@ && !defined $data;
+print "ok 15\n";
+
+undef $data;
+eval {
+ $dec_fc->process_msg($botan_lic_b64_garbage);
+ $dec_fc->set_default_msg(2);
+ $data = $dec_fc->read();
+};
+
+print "not " unless $@ && !defined $data;
+print "ok 16\n";
+
+
+# Encoder...
+
+eval { $f = Botan::Base64_Encoder->new(); };
+print "not " if $@ || !defined $f;
+print "ok 17\n";
+
+my $enc;
+eval { $enc = Botan::Pipe->new($f); };
+print "not " if $@ || !defined $enc;
+print "ok 18\n";
+
+eval { $f = Botan::Base64_Encoder->new(1, 5); };
+print "not " if $@ || !defined $f;
+print "ok 19\n";
+
+my $enc2;
+eval { $enc2 = Botan::Pipe->new($f); };
+print "not " if $@ || !defined $enc2;
+print "ok 20\n";
+
+undef $data;
+eval {
+ $enc->process_msg("Hello\n");
+ $data = $enc->read();
+};
+print "not " if $@ || $data ne "SGVsbG8K";
+print "ok 21\n";
+
+undef $data;
+eval {
+ $enc2->process_msg("Hello\n");
+ $data = $enc2->read();
+};
+print "not " if $@ || $data ne "SGVsb\nG8K\n";
+print "ok 22\n";
+
+
+# Encoder with decoder...
+
+my $p;
+eval {
+ $p = Botan::Pipe->new(
+ Botan::Base64_Encoder->new(),
+ Botan::Base64_Decoder->new(),
+ );
+};
+print "not " if $@ || !defined $p;
+print "ok 23\n";
+
+print "not " unless random_message_ok($p);
+print "ok 24\n";
diff --git a/wrappers/perl-xs/t/filt.t b/wrappers/perl-xs/t/filt.t
new file mode 100644
index 000000000..2a7b4c8ba
--- /dev/null
+++ b/wrappers/perl-xs/t/filt.t
@@ -0,0 +1,56 @@
+# vim: set ft=perl:
+# Before `make install' is performed this script should be runnable with
+# `make test'. After `make install' it should work as `perl test.pl'
+
+######################### We start with some black magic to print on failure.
+
+# Change 1..1 below to 1..last_test_to_print .
+# (It may become useful if the test is moved to ./t subdirectory.)
+
+BEGIN { $| = 1; print "1..5\n"; }
+END { print "not ok 1\n" unless $loaded; }
+
+use Botan;
+
+$loaded = 1;
+print "ok 1\n";
+
+######################### End of black magic.
+
+# Insert your test code below (better if it prints "ok 13"
+# (correspondingly "not ok 13") depending on the success of chunk 13
+# of the test code):
+
+use strict;
+
+my $pipe = Botan::Pipe->new(Botan::Hex_Encoder->new());
+
+print "not " unless $pipe;
+print "ok 2\n";
+
+$pipe->process_msg('FOO');
+
+print "not " if $pipe->read() ne '464F4F';
+print "ok 3\n";
+
+$pipe = Botan::Pipe->new(Botan::Hex_Encoder->new(0, 0, 1));
+
+print "not " unless $pipe;
+print "ok 4\n";
+
+$pipe->process_msg('FOO');
+
+print "not " if $pipe->read() ne '464f4f';
+print "ok 5\n";
+
+
+
+
+
+
+#my $pipe = Botan::Pipe->new(Botan::Base64_Encoder->new());
+#$pipe->process_msg('FOO');
+#
+#print "not " if $pipe->read() ne 'Rk9P';
+#print "ok 4\n";
+
diff --git a/wrappers/perl-xs/t/hex.t b/wrappers/perl-xs/t/hex.t
new file mode 100644
index 000000000..6f447b25c
--- /dev/null
+++ b/wrappers/perl-xs/t/hex.t
@@ -0,0 +1,256 @@
+# vim: set ft=perl:
+# Before `make install' is performed this script should be runnable with
+# `make test'. After `make install' it should work as `perl test.pl'
+
+######################### We start with some black magic to print on failure.
+
+# Change 1..1 below to 1..last_test_to_print .
+# (It may become useful if the test is moved to ./t subdirectory.)
+
+BEGIN { $| = 1; print "1..24\n"; }
+END { print "not ok 1\n" unless $loaded; }
+
+require 't/testutl.pl';
+use Botan;
+
+$loaded = 1;
+print "ok 1\n";
+
+######################### End of black magic.
+
+# Insert your test code below (better if it prints "ok 13"
+# (correspondingly "not ok 13") depending on the success of chunk 13
+# of the test code):
+
+use strict;
+
+# Data prep
+
+my ($hex, $hex_ws, $hex_garbage);
+while ( $_ = <DATA> )
+{
+ $hex_garbage .= $_;
+ s/[^[:xdigit:][:space:]]//g;
+ $hex_ws .= $_;
+ s/[^[:xdigit:]]//g;
+ $hex .= $_;
+}
+my $data_test = pack("H*", $hex);
+
+# Decoder...
+
+my $f;
+
+eval { $f = Botan::Hex_Decoder->new(&Botan::NONE); };
+print "not " if $@ || !defined $f;
+print "ok 2\n";
+
+my $dec;
+eval { $dec = Botan::Pipe->new($f); };
+print "not " if $@ || !defined $dec;
+print "ok 3\n";
+
+eval { $f = Botan::Hex_Decoder->new(&Botan::IGNORE_WS); };
+print "not " if $@ || !defined $f;
+print "ok 4\n";
+
+my $dec_is;
+eval { $dec_is = Botan::Pipe->new($f); };
+print "not " if $@ || !defined $dec_is;
+print "ok 5\n";
+
+eval { $f = Botan::Hex_Decoder->new(&Botan::FULL_CHECK); };
+print "not " if $@ || !defined $f;
+print "ok 6\n";
+
+my $dec_fc;
+eval { $dec_fc = Botan::Pipe->new($f); };
+print "not " if $@ || !defined $dec_fc;
+print "ok 7\n";
+
+
+# Testing clean hexadecimal input
+
+my $data;
+
+undef $data;
+eval {
+ $dec->process_msg($hex);
+ $data = $dec->read();
+};
+
+print "not " if $@ || $data ne $data_test;
+print "ok 8\n";
+
+undef $data;
+eval {
+ $dec_is->process_msg($hex);
+ $data = $dec_is->read();
+};
+
+print "not " if $@ || $data ne $data_test;
+print "ok 9\n";
+
+undef $data;
+eval {
+ $dec_fc->process_msg($hex);
+ $data = $dec_fc->read();
+};
+
+print "not " if $@ || $data ne $data_test;
+print "ok 10\n";
+
+
+# Testing hexadecimal input with whitespaces
+
+undef $data;
+eval {
+ $dec->process_msg($hex_ws);
+ $dec->set_default_msg(1);
+ $data = $dec->read();
+};
+
+print "not " if $@ || $data ne $data_test;
+print "ok 11\n";
+
+undef $data;
+eval {
+ $dec_is->process_msg($hex_ws);
+ $dec_is->set_default_msg(1);
+ $data = $dec_is->read();
+};
+
+print "not " if $@ || $data ne $data_test;
+print "ok 12\n";
+
+undef $data;
+eval {
+ $dec_fc->process_msg($hex_ws);
+ $dec_fc->set_default_msg(1);
+ $data = $dec_fc->read();
+};
+
+print "not " unless $@ && !defined $data;
+print "ok 13\n";
+
+
+# Testing hexadecimal input with garbage
+
+undef $data;
+eval {
+ $dec->process_msg($hex_garbage);
+ $dec->set_default_msg(2);
+ $data = $dec->read();
+};
+
+print "not " if $@ || $data ne $data_test;
+print "ok 14\n";
+
+undef $data;
+eval {
+ $dec_is->process_msg($hex_garbage);
+ $dec_is->set_default_msg(2);
+ $data = $dec_is->read();
+};
+
+print "not " unless $@ && !defined $data;
+print "ok 15\n";
+
+undef $data;
+eval {
+ $dec_fc->process_msg($hex_garbage);
+ $dec_fc->set_default_msg(2);
+ $data = $dec_fc->read();
+};
+
+print "not " unless $@ && !defined $data;
+print "ok 16\n";
+
+
+# Encoder...
+
+eval { $f = Botan::Hex_Encoder->new(); };
+print "not " if $@ || !defined $f;
+print "ok 17\n";
+
+my $enc;
+eval { $enc = Botan::Pipe->new($f); };
+print "not " if $@ || !defined $enc;
+print "ok 18\n";
+
+eval { $f = Botan::Hex_Encoder->new(1, 5, 1); };
+print "not " if $@ || !defined $f;
+print "ok 19\n";
+
+my $enc2;
+eval { $enc2 = Botan::Pipe->new($f); };
+print "not " if $@ || !defined $enc2;
+print "ok 20\n";
+
+undef $data;
+eval {
+ $enc->process_msg("Hello\n");
+ $data = $enc->read();
+};
+print "not " if $@ || $data ne "48656C6C6F0A";
+print "ok 21\n";
+
+undef $data;
+eval {
+ $enc2->process_msg("Hello\n");
+ $data = $enc2->read();
+};
+print "not " if $@ || $data ne "48656\nc6c6f\n0a\n";
+print "ok 22\n";
+
+
+# Encoder with decoder...
+
+my $p;
+eval {
+ $p = Botan::Pipe->new(
+ Botan::Hex_Encoder->new(),
+ Botan::Hex_Decoder->new(),
+ );
+};
+print "not " if $@ || !defined $p;
+print "ok 23\n";
+
+print "not " unless random_message_ok($p);
+print "ok 24\n";
+
+
+
+__DATA__
+cb13 4a4d 7522 1fd3 c6f6 7786 d04b 3043 ..JMu"....w..K..
+4552 4bcf 4d2b 9d71 0cfe 4d6a 1caf bcfd .RK.M+.q..Mj....
+8f91 6151 ff85 e900 7e6a bafc 15e9 ae51 ...Q....~j.....Q
+b14b 7210 bb40 5958 2b82 d49e b808 68a5 .Kr..@YX+.....h.
+7945 9dec f686 9b98 989e 826d 8088 6ee7 y..........m..n.
+d066 1eac 8c34 c461 bb54 7726 87ab d681 .........Tw&....
+a0be 52e5 1128 0cf2 759e cb2d e690 4ed9 ..R..(..u..-..N.
+7e88 bda7 2523 4a0f 185a 02b1 f898 fc41 ~...%#J..Z......
+dd48 fa87 945d 7611 b8c9 a50a 2de2 b670 .H...]v.....-..p
+0056 c8be 2cbb e7d0 1e70 4a3d 79f0 dce9 .V..,....pJ=y...
+b57f 154b 2b3a db73 f086 de11 9f3e 1641 ...K+:.s.....>..
+3a28 8b9b bb0f 682b 80db b791 89e0 62c0 :(....h+........
+7204 db97 5432 2eb0 a04e f38e 809f 7223 r...T....N....r#
+912e e552 1452 6dd2 e09f dd06 c715 7c1a ...R.Rm.......|.
+fe3d d6cc b6d0 a17a 27d7 4327 4e43 8af3 .=.....z'..'N...
+6eb5 e9f8 bfe9 34c3 6636 8243 358f 966d n..............m
+7d87 d17b 5c37 6acb 4972 f4ec 6806 bbde }..{\.j.Ir..h...
+2689 a019 a9e2 4101 7fe2 de72 bc03 eb5e &..........r...^
+b699 2d6b f8cd a08e 6e01 edfc a81a 94b6 ..-k....n.......
+9073 15fb efb2 c8d9 9f85 6633 85f1 e9d0 .s..............
+20ce 578b ab9d 2e51 b947 69bf fba5 82c6 .W....Q.Gi.....
+2ed0 dd36 d679 a399 7db3 8a0d cdef 0eda .....y..}.......
+e761 e7f1 5b17 3f67 0c83 215a eddf 9d2a ....[.?g..!Z...*
+5e70 0a77 c92e 94e1 a82b fd7c f10a 894f ^p.w.....+.|...O
+2955 f0e8 7398 f409 2040 b797 da03 a5a6 )U..s... @......
+7ba4 c3c9 2659 b9f7 6a56 e17a b481 983f {...&Y..jV.z...?
+00ed 3cc8 5a22 ad5c b6e0 3566 d717 35a6 ..<.Z".\........
+1523 4104 de63 477e fd24 68e5 e816 98df .#....G~.$h.....
+1747 417e db72 a76a be5b b9dc 3dfb 2d05 .G.~.r.j.[..=.-.
+d27f e597 eafc 9a29 15c5 792d 9c88 9aea .......)..y-....
+485e e431 96c3 7723 da6d 28b2 477a fd12 H^....w#.m(.Gz..
+e645 5dcd 7d5a d8b4 7acc 10b2 b41a e11d ..].}Z..z.......
diff --git a/wrappers/perl-xs/t/oid.t b/wrappers/perl-xs/t/oid.t
new file mode 100644
index 000000000..66204541f
--- /dev/null
+++ b/wrappers/perl-xs/t/oid.t
@@ -0,0 +1,45 @@
+# vim: set ft=perl:
+# Before `make install' is performed this script should be runnable with
+# `make test'. After `make install' it should work as `perl test.pl'
+
+######################### We start with some black magic to print on failure.
+
+# Change 1..1 below to 1..last_test_to_print .
+# (It may become useful if the test is moved to ./t subdirectory.)
+
+BEGIN { $| = 1; print "1..6\n"; }
+END { print "not ok 1\n" unless $loaded; }
+
+use Botan;
+
+$loaded = 1;
+print "ok 1\n";
+
+######################### End of black magic.
+
+# Insert your test code below (better if it prints "ok 13"
+# (correspondingly "not ok 13") depending on the success of chunk 13
+# of the test code):
+
+use strict;
+
+print "not " unless Botan::OIDS::have_oid('X520.CommonName');
+print "ok 2\n";
+
+my $oid_c = Botan::OID->new('2.5.4.3');
+print "not " if Botan::OIDS::lookup_by_oid($oid_c) ne 'X520.CommonName';
+print "ok 3\n";
+
+my $oid_x = Botan::OIDS::lookup_by_name('X520.CommonName');
+print "not " if $oid_x->as_string() ne '2.5.4.3';
+print "ok 4\n";
+
+my $oid_foo_num = '1.2.3.4.5.6.7.8.9.10.11.12.13.14.15';
+my $oid_foo = Botan::OID->new($oid_foo_num);
+print "not " if Botan::OIDS::lookup_by_oid($oid_foo) ne $oid_foo_num;
+print "ok 5\n";
+
+Botan::OIDS::add_oid($oid_foo, 'Zito.Foo');
+
+print "not " if Botan::OIDS::lookup_by_oid($oid_foo) ne 'Zito.Foo';
+print "ok 6\n";
diff --git a/wrappers/perl-xs/t/pipe.t b/wrappers/perl-xs/t/pipe.t
new file mode 100644
index 000000000..f850d8519
--- /dev/null
+++ b/wrappers/perl-xs/t/pipe.t
@@ -0,0 +1,98 @@
+# vim: set ft=perl:
+# Before `make install' is performed this script should be runnable with
+# `make test'. After `make install' it should work as `perl test.pl'
+
+######################### We start with some black magic to print on failure.
+
+# Change 1..1 below to 1..last_test_to_print .
+# (It may become useful if the test is moved to ./t subdirectory.)
+
+BEGIN { $| = 1; print "1..20\n"; }
+END { print "not ok 1\n" unless $loaded; }
+
+use Botan;
+
+$loaded = 1;
+print "ok 1\n";
+
+######################### End of black magic.
+
+# Insert your test code below (better if it prints "ok 13"
+# (correspondingly "not ok 13") depending on the success of chunk 13
+# of the test code):
+
+use strict;
+
+my $pipe = Botan::Pipe->new();
+
+print "not " unless $pipe;
+print "ok 2\n";
+
+$pipe->start_msg();
+$pipe->write('Hello world');
+$pipe->end_msg();
+
+print "not " if $pipe->message_count() != 1;
+print "ok 3\n";
+
+print "not " if $pipe->remaining() != 11;
+print "ok 4\n";
+
+print "not " if $pipe->end_of_data();
+print "ok 5\n";
+
+print "not " if $pipe->read() ne 'Hello world';
+print "ok 6\n";
+
+print "not " if $pipe->remaining() != 0;
+print "ok 7\n";
+
+print "not " unless $pipe->end_of_data();
+print "ok 8\n";
+
+$pipe->process_msg('Hello world');
+
+print "not " if $pipe->message_count() != 2;
+print "ok 9\n";
+
+my $msg_num = $pipe->message_count() -1;
+
+print "not " if $pipe->read(5, $msg_num) ne 'Hello';
+print "ok 10\n";
+
+print "not " if $pipe->read(6, $msg_num) ne ' world';
+print "ok 11\n";
+
+print "not " if $pipe->remaining() != 0;
+print "ok 12\n";
+
+print "not " unless $pipe->end_of_data();
+print "ok 13\n";
+
+$pipe->process_msg("The\0string\0with\0null\0chars\0");
+$msg_num = $pipe->message_count() -1;
+
+print "not " if $pipe->read(80, $msg_num) ne "The\0string\0with\0null\0chars\0";
+print "ok 14\n";
+
+$pipe->process_msg('FOO BAR');
+$pipe->set_default_msg($pipe->message_count() -1);
+
+print "not " if $pipe->peek(3) ne 'FOO';
+print "ok 15\n";
+
+print "not " if $pipe->peek(3, 4) ne 'BAR';
+print "ok 16\n";
+
+print "not " if $pipe->peek() ne 'FOO BAR';
+print "ok 17\n";
+
+print "not " if $pipe->read() ne 'FOO BAR';
+print "ok 18\n";
+
+print "not " if $pipe->remaining() != 0;
+print "ok 19\n";
+
+print "not " unless $pipe->end_of_data();
+print "ok 20\n";
+
diff --git a/wrappers/perl-xs/t/testutl.pl b/wrappers/perl-xs/t/testutl.pl
new file mode 100644
index 000000000..add6f6a45
--- /dev/null
+++ b/wrappers/perl-xs/t/testutl.pl
@@ -0,0 +1,26 @@
+#!/usr/bin/perl
+
+sub random_message_ok
+{
+ my ($pipe, $iter, $chunkmax) = @_;
+ $iter = 100 unless defined $iter;
+ $chunkmax = 300 unless defined $chunkmax;
+ eval {
+ my $input = '';
+ $pipe->start_msg();
+ for(my $i = 0; $i < $iter; $i++)
+ {
+ my $chunk = '';
+ my $chunklen = int(rand($chunkmax));
+ $chunk .= pack("C", int(rand(256))) while $chunklen--;
+ $input .= $chunk;
+ $pipe->write($chunk);
+ }
+ $pipe->end_msg();
+ my $msg_num = $pipe->message_count() -1;
+ my $output = $pipe->read(0xFFFFFFFF, $msg_num);
+ return $input eq $output;
+ };
+}
+
+1;
diff --git a/wrappers/perl-xs/t/x509cert.t b/wrappers/perl-xs/t/x509cert.t
new file mode 100644
index 000000000..2a943aeac
--- /dev/null
+++ b/wrappers/perl-xs/t/x509cert.t
@@ -0,0 +1,42 @@
+# vim: set ft=perl:
+# Before `make install' is performed this script should be runnable with
+# `make test'. After `make install' it should work as `perl test.pl'
+
+######################### We start with some black magic to print on failure.
+
+# Change 1..1 below to 1..last_test_to_print .
+# (It may become useful if the test is moved to ./t subdirectory.)
+
+BEGIN { $| = 1; print "1..4\n"; }
+END { print "not ok 1\n" unless $loaded; }
+
+use Botan;
+
+$loaded = 1;
+print "ok 1\n";
+
+######################### End of black magic.
+
+# Insert your test code below (better if it prints "ok 13"
+# (correspondingly "not ok 13") depending on the success of chunk 13
+# of the test code):
+
+use strict;
+
+my $cert = Botan::X509_Certificate->new('data/ca.cert.der');
+
+print "not " if $cert->x509_version() != 3;
+print "ok 2\n";
+
+print "not " if $cert->start_time() ne '2000/8/20 21:48:00 UTC';
+print "ok 3\n";
+
+print "not " if $cert->end_time() ne '2002/8/10 21:48:00 UTC';
+print "ok 4\n";
+
+#my $subject = $cert->subject_dn()->get_attributes();
+#print STDERR "subject=", join(',', @{$subject}), "\n";
+#
+#my $issuer = $cert->issuer_dn()->get_attributes();
+#print STDERR "issuer=", join(',', @{$issuer}), "\n";
+#
diff --git a/wrappers/perl-xs/typemap b/wrappers/perl-xs/typemap
new file mode 100644
index 000000000..d7403d40d
--- /dev/null
+++ b/wrappers/perl-xs/typemap
@@ -0,0 +1,62 @@
+TYPEMAP
+
+Botan__ASN1_String * O_OBJECT
+Botan__AlgorithmIdentifier * O_OBJECT
+Botan__AlternativeName * O_OBJECT
+Botan__Attribute * O_OBJECT
+Botan__Base64_Decoder * O_EXTOBJECT
+Botan__Base64_Encoder * O_EXTOBJECT
+Botan__Chain * O_EXTOBJECT
+Botan__Extension * O_OBJECT
+Botan__Filter * O_EXTOBJECT
+Botan__Fork * O_EXTOBJECT
+Botan__Hex_Decoder * O_EXTOBJECT
+Botan__Hex_Encoder * O_EXTOBJECT
+Botan__OID * O_OBJECT
+Botan__Pipe * O_OBJECT
+Botan__X509_Certificate * O_OBJECT
+Botan__X509_DN * O_OBJECT
+Botan__X509_Time * O_OBJECT
+Botan__u32bit T_UV
+
+
+######################################################################
+OUTPUT
+
+# The Perl object is blessed into 'CLASS', which should be a
+# char* having the name of the package for the blessing.
+O_OBJECT
+ sv_setref_pv($arg, CLASS, (void*)$var);
+
+O_EXTOBJECT
+ sv_setref_pv($arg, CLASS, (void*)$var);
+ sv_magic(SvRV($arg), 0, '~', (char *)&oi_init, sizeof(oi_init));
+
+
+######################################################################
+INPUT
+
+O_OBJECT
+ if ( sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVMG) )
+ $var = ($type)SvIV((SV*)SvRV( $arg ));
+ else
+ croak(\"${Package}::$func_name() -- \"
+ \"$var is not a blessed SV reference\");
+
+# The pointer variable "ObjectInfo *${var}_oi;" must be declared
+# in PREINIT section. I don't know how to emit this declaration safely here.
+O_EXTOBJECT
+ if ( sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVMG) )
+ $var = ($type)SvIV((SV*)SvRV($arg));
+ else
+ croak(\"${Package}::$func_name() -- \"
+ \"$var is not a blessed SV reference\");
+ {
+ MAGIC *mg = mg_find(SvRV($arg), '~');
+ if ( mg == 0
+ || mg->mg_len != sizeof(ObjectInfo)
+ || *(I32 *)(mg->mg_ptr) != ObjectInfo::SIGNVAL )
+ croak(\"${Package}::$func_name() -- \"
+ \"private magic data for $var invalid\");
+ ${var}_oi = (ObjectInfo *)(mg->mg_ptr);
+ }
diff --git a/wrappers/swig/Makefile b/wrappers/swig/Makefile
new file mode 100644
index 000000000..ff55c793c
--- /dev/null
+++ b/wrappers/swig/Makefile
@@ -0,0 +1,32 @@
+LANG=-python
+LANG_INC=/usr/include/python2.3
+
+CFLAGS=$(shell botan-config --cflags)
+LIBS=$(shell botan-config --libs)
+
+CXX = g++ -g
+SWIG = swig -Wall
+
+all: _botan.so
+
+_botan.so: base.o pipe.o filter.o botan_wrap.o
+ $(CXX) -shared $^ $(LIBS) -o $@
+
+botan_wrap.cpp: botan.swg base.h
+ $(SWIG) $(LANG) -c++ -o $@ $<
+
+botan_wrap.o: botan_wrap.cpp
+ $(CXX) $(CFLAGS) -I$(LANG_INC) -c $^ -o $@
+
+base.o: base.cpp base.h
+ $(CXX) $(CFLAGS) -c $< -o $@
+
+pipe.o: pipe.cpp base.h
+ $(CXX) $(CFLAGS) -c $< -o $@
+
+filter.o: filter.cpp base.h
+ $(CXX) $(CFLAGS) -c $< -o $@
+
+clean:
+ rm -f *.o _botan.so botan.py botan.pyc
+ rm -f *_wrap.o *_wrap.cpp
diff --git a/wrappers/swig/base.cpp b/wrappers/swig/base.cpp
new file mode 100644
index 000000000..2550b915b
--- /dev/null
+++ b/wrappers/swig/base.cpp
@@ -0,0 +1,61 @@
+/*************************************************
+* SWIG Interface for basic Botan interface *
+* (C) 1999-2003 The Botan Project *
+*************************************************/
+
+#include "base.h"
+#include <botan/init.h>
+
+#include <stdio.h>
+
+/*************************************************
+* Initialize the library *
+*************************************************/
+LibraryInitializer::LibraryInitializer(const char* args)
+ {
+ Botan::Init::initialize(args);
+ }
+
+/*************************************************
+* Shut down the library *
+*************************************************/
+LibraryInitializer::~LibraryInitializer()
+ {
+ Botan::Init::deinitialize();
+ }
+
+/*************************************************
+* Create a SymmetricKey *
+*************************************************/
+SymmetricKey::SymmetricKey(const std::string& str)
+ {
+ key = new Botan::SymmetricKey(str);
+ printf("STR CON: %p %p\n", this, key);
+ }
+
+/*************************************************
+* Create a SymmetricKey *
+*************************************************/
+SymmetricKey::SymmetricKey(u32bit n)
+ {
+ key = new Botan::SymmetricKey(n);
+ printf("N CON: %p %p\n", this, key);
+ }
+
+/*************************************************
+* Destroy a SymmetricKey *
+*************************************************/
+SymmetricKey::~SymmetricKey()
+ {
+ printf("DESTR: %p %p\n", this, key);
+ delete key;
+ key = 0;
+ //printf("deleted\n");
+ }
+
+/*************************************************
+* Create an InitializationVector *
+*************************************************/
+InitializationVector::InitializationVector(const std::string& str) : iv(str)
+ {
+ }
diff --git a/wrappers/swig/base.h b/wrappers/swig/base.h
new file mode 100644
index 000000000..c3fd8426e
--- /dev/null
+++ b/wrappers/swig/base.h
@@ -0,0 +1,102 @@
+/*************************************************
+* SWIG Interface for Botan *
+* (C) 1999-2003 The Botan Project *
+*************************************************/
+
+#ifndef BOTAN_WRAP_BASE_H__
+#define BOTAN_WRAP_BASE_H__
+
+#include <botan/pipe.h>
+
+#if !defined(SWIG)
+ #define OUTPUT
+ #define INOUT
+#endif
+
+/*************************************************
+* Typedefs *
+*************************************************/
+typedef unsigned char byte;
+typedef unsigned int u32bit;
+
+/*************************************************
+* Library Initalization/Shutdown Object *
+*************************************************/
+class LibraryInitializer
+ {
+ public:
+ LibraryInitializer(const char*);
+ ~LibraryInitializer();
+ };
+
+/*************************************************
+* Symmetric Key Object *
+*************************************************/
+class SymmetricKey
+ {
+ public:
+ std::string as_string() const { return key->as_string(); }
+ u32bit length() const { return key->length(); }
+ SymmetricKey(u32bit = 0);
+ SymmetricKey(const std::string&);
+ ~SymmetricKey();
+ private:
+ Botan::SymmetricKey* key;
+ };
+
+/*************************************************
+* Initialization Vector Object *
+*************************************************/
+class InitializationVector
+ {
+ public:
+ std::string as_string() const { return iv.as_string(); }
+ u32bit length() const { return iv.length(); }
+ InitializationVector(u32bit n = 0) { iv.change(n); }
+ InitializationVector(const std::string&);
+ private:
+ Botan::InitializationVector iv;
+ };
+
+/*************************************************
+* Filter Object *
+*************************************************/
+class Filter
+ {
+ public:
+ Filter(const char*);
+ //Filter(const char*, const SymmetricKey&);
+ //Filter(const char*, const SymmetricKey&, const InitializationVector&);
+ ~Filter();
+ private:
+ friend class Pipe;
+ Botan::Filter* filter;
+ bool pipe_owns;
+ };
+
+/*************************************************
+* Pipe Object *
+*************************************************/
+class Pipe
+ {
+ public:
+ static const u32bit DEFAULT_MESSAGE = 0xFFFFFFFF;
+
+ void write_file(const char*);
+ void write_string(const char*);
+
+ u32bit read(byte*, u32bit, u32bit = DEFAULT_MESSAGE);
+ std::string read_all_as_string(u32bit = DEFAULT_MESSAGE);
+
+ u32bit remaining(u32bit = DEFAULT_MESSAGE);
+
+ void start_msg();
+ void end_msg();
+
+ Pipe(Filter* = 0, Filter* = 0, Filter* = 0, Filter* = 0);
+ ~Pipe();
+ private:
+ Botan::Pipe* pipe;
+ };
+
+#endif
diff --git a/wrappers/swig/botan.swg b/wrappers/swig/botan.swg
new file mode 100644
index 000000000..9088f4272
--- /dev/null
+++ b/wrappers/swig/botan.swg
@@ -0,0 +1,26 @@
+/*************************************************
+* SWIG Interface for Botan *
+*************************************************/
+%module botan
+
+%include "typemaps.i"
+%include "std_string.i"
+%include "exception.i"
+%include "constraints.i"
+%include "carrays.i"
+
+%{
+#include "base.h"
+%}
+
+%exception {
+ try {
+ $action
+ }
+ catch(std::exception& e)
+ {
+ SWIG_exception(SWIG_RuntimeError, e.what());
+ }
+}
+
+%include "base.h"
diff --git a/wrappers/swig/doit.py b/wrappers/swig/doit.py
new file mode 100755
index 000000000..98bc97087
--- /dev/null
+++ b/wrappers/swig/doit.py
@@ -0,0 +1,49 @@
+#!/usr/bin/python2
+
+import botan
+
+def hash_it(hash, input):
+ f1 = botan.Filter("MD5")
+ f2 = botan.Filter("Hex_Encoder")
+ pipe = botan.Pipe(f1, f2)
+
+ pipe.start_msg()
+ pipe.write_string(input)
+ pipe.end_msg()
+
+ print pipe.remaining()
+
+ out = pipe.read(0)
+
+
+
+
+def main:
+ init = botan.LibraryInitializer
+
+ print hash_it("MD5", "foo")
+
+
+ key1 = botan.SymmetricKey("ABCD")
+ print key1.as_string()
+ key2 = botan.SymmetricKey(16)
+ print key2.as_string()
+
+ iv1 = botan.InitializationVector(8)
+ print iv1.as_string()
+
+
+ f3 = pipe.read(pipe.remaining())
+
+ size = pipe.remaining()
+ out = botan.byte_array(size)
+ pipe.read(out.cast,size)
+
+ for i in range (0,size):
+ print "%02X" % out[i]
+
+ print pipe.read_all_as_string()
+
+if __name__ == "__main__":
+ sys.exit(main())
+
diff --git a/wrappers/swig/filter.cpp b/wrappers/swig/filter.cpp
new file mode 100644
index 000000000..ec9ce6603
--- /dev/null
+++ b/wrappers/swig/filter.cpp
@@ -0,0 +1,39 @@
+/*************************************************
+* SWIG Interface for Filter Retrieval *
+* (C) 1999-2003 The Botan Project *
+*************************************************/
+
+#include "base.h"
+#include <botan/lookup.h>
+#include <botan/filters.h>
+
+/*************************************************
+* Filter Creation *
+*************************************************/
+Filter::Filter(const char* filt_string)
+ {
+ filter = 0;
+ pipe_owns = false;
+
+ /*
+ Fixme: This is all so totally wrong. It needs to have full argument
+ processing for everything, all that kind of crap.
+ */
+ const std::string filt_name = filt_string;
+
+ if(Botan::have_hash(filt_name))
+ filter = new Botan::Hash_Filter(filt_name);
+ else if(filt_name == "Hex_Encoder")
+ filter = new Botan::Hex_Encoder;
+ }
+
+/*************************************************
+* Filter Destruction *
+*************************************************/
+Filter::~Filter()
+ {
+ /*
+ if(!pipe_owns)
+ delete filter;
+ */
+ }
diff --git a/wrappers/swig/pipe.cpp b/wrappers/swig/pipe.cpp
new file mode 100644
index 000000000..2ccdd5dfd
--- /dev/null
+++ b/wrappers/swig/pipe.cpp
@@ -0,0 +1,89 @@
+/*************************************************
+* SWIG Interface for Botan Pipe API *
+* (C) 1999-2003 The Botan Project *
+*************************************************/
+
+#include "base.h"
+#include <botan/pipe.h>
+
+#include <stdio.h>
+
+/*************************************************
+* Write the contents of a file into a Pipe *
+*************************************************/
+void Pipe::write_file(const char* filename)
+ {
+ Botan::DataSource_Stream in(filename);
+ pipe->write(in);
+ }
+
+/*************************************************
+* Write the contents of a string into a Pipe *
+*************************************************/
+void Pipe::write_string(const char* string)
+ {
+ pipe->write(string);
+ }
+
+/*************************************************
+* Read the contents of a Pipe into a buffer *
+*************************************************/
+u32bit Pipe::read(byte* buf, u32bit length, u32bit msg)
+ {
+ printf("read %p %d\n", buf, length);
+ return 0;
+ //return pipe->read(buf, length, msg);
+ }
+
+/*************************************************
+* Read the contents of a Pipe as a string *
+*************************************************/
+std::string Pipe::read_all_as_string(u32bit msg)
+ {
+ return pipe->read_all_as_string(msg);
+ }
+
+/*************************************************
+* Find out how much stuff the Pipe still has *
+*************************************************/
+u32bit Pipe::remaining(u32bit msg)
+ {
+ return pipe->remaining();
+ }
+
+/*************************************************
+* Start a new message *
+*************************************************/
+void Pipe::start_msg()
+ {
+ pipe->start_msg();
+ }
+
+/*************************************************
+* End the current msessage *
+*************************************************/
+void Pipe::end_msg()
+ {
+ pipe->end_msg();
+ }
+
+/*************************************************
+* Create a new Pipe *
+*************************************************/
+Pipe::Pipe(Filter* f1, Filter* f2, Filter* f3, Filter* f4)
+ {
+ pipe = new Botan::Pipe();
+
+ if(f1) { pipe->append(f1->filter); f1->pipe_owns = true; }
+ if(f2) { pipe->append(f2->filter); f2->pipe_owns = true; }
+ if(f3) { pipe->append(f3->filter); f3->pipe_owns = true; }
+ if(f4) { pipe->append(f4->filter); f4->pipe_owns = true; }
+ }
+
+/*************************************************
+* Destroy this Pipe *
+*************************************************/
+Pipe::~Pipe()
+ {
+ delete pipe;
+ }
diff --git a/wrappers/swig/pk.swg b/wrappers/swig/pk.swg
new file mode 100644
index 000000000..8e03cf120
--- /dev/null
+++ b/wrappers/swig/pk.swg
@@ -0,0 +1,8 @@
+%module botan
+
+%{
+#undef ANY
+#include "botan/pubkey.h"
+%}
+
+%include "botan/pubkey.h"
diff --git a/wrappers/swig/readme.txt b/wrappers/swig/readme.txt
new file mode 100644
index 000000000..a9965d914
--- /dev/null
+++ b/wrappers/swig/readme.txt
@@ -0,0 +1,34 @@
+This is the beginning of an attempt to SWIG-ify Botan so it can be accessed by
+other languages. You should use the latest SWIG 1.3 release (I am currently
+using SWIG 1.3.19). Currently I am only testing this code with Python 2.2.1,
+since that is the language I am mainly interested in at this point. Feel free
+to send me patches so this is usable with Perl or whatever.
+
+I'm not attempting to make everything in Botan usable from a script -
+basically, I just want the parts that *I* want to use. Most things are not
+supported yet, and there are lots of bugs in the stuff that does exist. If
+there is something in particular that you would like to be able to use from a
+script, let me know (patches are good, too).
+
+Todo:
+ * Why does it seg fault if we don't create a LibraryInitializer. It should
+ throw an exception, like it does in C++. Maybe have it init Botan when the
+ module is loaded? That seems a lot cleaner/nicer, but I don't know how to
+ do it yet.
+ * Lots of problems with exceptions
+ * Use constraints to prevent bad args when possible
+ * Pipe/Filter
+ - Better argument processing for all filters
+ - Support for ciphers, MACs, etc
+ - Chain + Fork
+ - Support for append/prepend/pop/reset in Pipe?
+ * Public Key Crypto
+ - RSA
+ - DSA
+ - DH
+ - Generic X.509 and PKCS #8 stuff
+ * PKI
+ - X.509 certs + CRLs
+ - PKCS #10 requests
+ - X.509 stores
+ - X.509 CA
diff --git a/wrappers/swig/tests/block.py b/wrappers/swig/tests/block.py
new file mode 100644
index 000000000..593937c81
--- /dev/null
+++ b/wrappers/swig/tests/block.py
@@ -0,0 +1,52 @@
+#!/usr/bin/python
+
+import botan, base64
+
+class MyCipher(botan.BlockCipher):
+ def __init__(self):
+ botan.BlockCipher.__init__(self, 16, 16, 32, 8)
+ def encrypt(self, val):
+ print "encrypt", val
+ return val.swapcase()
+ def decrypt(self, val):
+ print "decrypt", val
+ return val.swapcase()
+ def set_key(self, key):
+ print "set_key", key
+ def clone(self):
+ print "cloning"
+ return MyCipher()
+ def name(self):
+ print "naming"
+ return "MyCipher"
+
+cipher = botan.BlockCipher("AES-128")
+
+print cipher.block_size
+print cipher.keylength_min
+print cipher.keylength_max
+print cipher.keylength_mod
+print cipher.name()
+
+for kl in range(1, 128):
+ if cipher.valid_keylength(kl):
+ print "1",
+ else:
+ print "0",
+print
+key = botan.SymmetricKey(16)
+
+cipher.set_key(key)
+ciphertext = cipher.encrypt("ABCDEFGH12345678")
+print base64.b16encode(ciphertext)
+
+cipher2 = cipher.clone()
+cipher2.set_key(key)
+
+plaintext = cipher2.decrypt(ciphertext)
+print plaintext
+
+botan.get_info(cipher)
+
+mycipher = MyCipher()
+botan.get_info(mycipher)
diff --git a/wrappers/swig/tests/block2.py b/wrappers/swig/tests/block2.py
new file mode 100644
index 000000000..5faccaf9a
--- /dev/null
+++ b/wrappers/swig/tests/block2.py
@@ -0,0 +1,44 @@
+#!/usr/bin/python
+
+import botan, base64
+
+class MyCipher(botan.BlockCipherImpl):
+ def __init__(self):
+ botan.BlockCipherImpl.__init__(self, 8, 8, 16, 1)
+
+ def name(self):
+ return "MyCipher"
+
+ def encrypt(self, input):
+ return input.swapcase()
+
+ def decrypt(self, input):
+ return input.swapcase()
+
+ def set_key(self, key):
+ print "Got key",key
+
+def test(cipher):
+ print
+ print cipher
+ print "Testing", cipher.name()
+ print cipher.block_size
+ print cipher.keylength_min, cipher.keylength_max, cipher.keylength_mod
+ for i in range(1, 64):
+ if cipher.valid_keylength(i):
+ print "1",
+ else:
+ print "0",
+ print
+ cipher.set_key(botan.SymmetricKey(16))
+ ciphertext = cipher.encrypt("aBcDeFgH" * (cipher.block_size / 8))
+ print repr(ciphertext)
+ print cipher.decrypt(ciphertext)
+
+def main():
+ test(botan.BlockCipher("Blowfish"))
+ test(MyCipher())
+ test(botan.BlockCipher("AES"))
+
+if __name__ == "__main__":
+ main()
diff --git a/wrappers/swig/tests/encrypt.py b/wrappers/swig/tests/encrypt.py
new file mode 100644
index 000000000..9896777d4
--- /dev/null
+++ b/wrappers/swig/tests/encrypt.py
@@ -0,0 +1,37 @@
+#!/usr/bin/python
+
+import sys, botan
+
+def encrypt(input):
+ cipher_key = botan.SymmetricKey("AABB")
+ print cipher_key.length
+ cipher_key = botan.SymmetricKey("AABBCCDD")
+ print cipher_key.length
+
+ cipher = botan.Filter("ARC4", key = cipher_key)
+
+ pipe = botan.Pipe(cipher, botan.Filter("Hex_Encoder"))
+
+ pipe.start_msg()
+ pipe.write(input)
+ pipe.end_msg()
+
+ str = pipe.read_all()
+ print str
+ return str
+
+def decrypt(input):
+ pipe = botan.Pipe(botan.Filter("Hex_Decoder"),
+ botan.Filter("ARC4",
+ key = botan.SymmetricKey("AABBCCDD")))
+
+ pipe.process_msg(input)
+ return pipe.read_all()
+
+def main():
+ ciphertext = encrypt("hi chappy")
+ print ciphertext
+ print decrypt(ciphertext)
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/wrappers/swig/tests/filter.py b/wrappers/swig/tests/filter.py
new file mode 100644
index 000000000..2b65d9ff2
--- /dev/null
+++ b/wrappers/swig/tests/filter.py
@@ -0,0 +1,27 @@
+#!/usr/bin/python
+
+import sys, botan
+
+class MyFilter(botan.FilterObj):
+ def write(self, input):
+ print "MyFilter::write",input
+ self.send(input)
+ def start_msg(self):
+ print "MyFilter::start_msg"
+ def end_msg(self):
+ print "MyFilter::end_msg"
+ def __del__(self):
+ print "~MyFilter"
+
+def main():
+ filter = MyFilter()
+
+ pipe = botan.Pipe(botan.Filter("Hex_Encoder"), filter,
+ botan.Filter("Hex_Decoder"))
+ pipe.start_msg()
+ pipe.write("hi chappy")
+ pipe.end_msg()
+ print pipe.read_all()
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/wrappers/swig/tests/hash.py b/wrappers/swig/tests/hash.py
new file mode 100644
index 000000000..930b8c81a
--- /dev/null
+++ b/wrappers/swig/tests/hash.py
@@ -0,0 +1,30 @@
+#!/usr/bin/python
+
+import botan, base64, md5
+
+class PyMD5(botan.HashFunctionImpl):
+ def name(self):
+ return "PyMD5"
+ def update(self, input):
+ self.md5.update(input)
+ def final(self):
+ output = self.md5.digest()
+ self.md5 = md5.new()
+ return output
+ def __init__(self):
+ botan.HashFunctionImpl.__init__(self, 16, 64)
+ self.md5 = md5.new()
+
+hash = botan.HashFunction("SHA-256")
+
+print hash.name()
+print hash.digest_size
+
+hash.update("hi")
+hash.update(" ")
+hash.update("chappy")
+print base64.b16encode(hash.final())
+
+hash2 = PyMD5()
+hash2.update("hi chappy")
+print base64.b16encode(hash2.final())
diff --git a/wrappers/swig/tests/mac.py b/wrappers/swig/tests/mac.py
new file mode 100644
index 000000000..6110b6102
--- /dev/null
+++ b/wrappers/swig/tests/mac.py
@@ -0,0 +1,12 @@
+#!/usr/bin/python
+
+import botan, base64
+
+mac = botan.MAC("HMAC(SHA-512)")
+
+print mac.name
+print mac.output_length
+
+mac.set_key(botan.SymmetricKey("abcd"))
+mac.update("hi chappy")
+print base64.b16encode(mac.final())
diff --git a/wrappers/swig/tests/pubkey.py b/wrappers/swig/tests/pubkey.py
new file mode 100644
index 000000000..456c52069
--- /dev/null
+++ b/wrappers/swig/tests/pubkey.py
@@ -0,0 +1,10 @@
+#!/usr/bin/python
+
+import botan
+
+key = botan.X509_PublicKey("rsapub.pem")
+print key
+print key.key_id()
+print key.max_input_bits
+print key.algo
+print key.oid
diff --git a/wrappers/swig/tests/stream.py b/wrappers/swig/tests/stream.py
new file mode 100644
index 000000000..59d3ffa16
--- /dev/null
+++ b/wrappers/swig/tests/stream.py
@@ -0,0 +1,17 @@
+#!/usr/bin/python
+
+import botan, base64
+
+cipher = botan.StreamCipher("ARC4")
+
+print cipher.name
+
+key = botan.SymmetricKey(16)
+
+cipher.set_key(key)
+ciphertext = cipher.crypt("hi chappy")
+
+cipher.set_key(key)
+plaintext = cipher.crypt(ciphertext)
+
+print plaintext
diff --git a/wrappers/swig/x509.swg b/wrappers/swig/x509.swg
new file mode 100644
index 000000000..736d3a385
--- /dev/null
+++ b/wrappers/swig/x509.swg
@@ -0,0 +1,9 @@
+%module botan
+
+class X509_Certificate
+ {
+ public:
+
+
+ private:
+ };