diff options
Diffstat (limited to 'wrappers/boost-python')
-rw-r--r-- | wrappers/boost-python/Makefile | 26 | ||||
-rw-r--r-- | wrappers/boost-python/botan/__init__.py | 27 | ||||
-rwxr-xr-x | wrappers/boost-python/nisttest.py | 61 | ||||
-rw-r--r-- | wrappers/boost-python/results.txt | 60 | ||||
-rw-r--r-- | wrappers/boost-python/src/block.cpp | 152 | ||||
-rw-r--r-- | wrappers/boost-python/src/common.h | 45 | ||||
-rw-r--r-- | wrappers/boost-python/src/core.cpp | 43 | ||||
-rw-r--r-- | wrappers/boost-python/src/filter.cpp | 176 | ||||
-rw-r--r-- | wrappers/boost-python/src/hash.cpp | 108 | ||||
-rw-r--r-- | wrappers/boost-python/src/macs.cpp | 59 | ||||
-rw-r--r-- | wrappers/boost-python/src/pk.cpp | 125 | ||||
-rw-r--r-- | wrappers/boost-python/src/stream.cpp | 54 | ||||
-rw-r--r-- | wrappers/boost-python/src/x509.cpp | 140 |
13 files changed, 1076 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)); + } + } |