aboutsummaryrefslogtreecommitdiffstats
path: root/src/wrap
diff options
context:
space:
mode:
Diffstat (limited to 'src/wrap')
-rw-r--r--src/wrap/python/__init__.py4
-rw-r--r--src/wrap/python/core.cpp203
-rw-r--r--src/wrap/python/filter.cpp178
-rw-r--r--src/wrap/python/pk.cpp125
-rw-r--r--src/wrap/python/python_botan.h51
-rw-r--r--src/wrap/python/x509.cpp140
6 files changed, 701 insertions, 0 deletions
diff --git a/src/wrap/python/__init__.py b/src/wrap/python/__init__.py
new file mode 100644
index 000000000..2df9a456f
--- /dev/null
+++ b/src/wrap/python/__init__.py
@@ -0,0 +1,4 @@
+from _botan import *
+
+# Initialize the library when the module is imported
+init = LibraryInitializer()
diff --git a/src/wrap/python/core.cpp b/src/wrap/python/core.cpp
new file mode 100644
index 000000000..1992e3d61
--- /dev/null
+++ b/src/wrap/python/core.cpp
@@ -0,0 +1,203 @@
+/*
+* Boost.Python module definition
+* (C) 1999-2007 Jack Lloyd
+*/
+
+#include <botan/init.h>
+#include <botan/pipe.h>
+#include <botan/lookup.h>
+using namespace Botan;
+
+#include "python_botan.h"
+
+class Python_RandomNumberGenerator
+ {
+ public:
+ Python_RandomNumberGenerator()
+ { rng = RandomNumberGenerator::make_rng(); }
+ ~Python_RandomNumberGenerator() { delete rng; }
+
+ std::string name() const { return rng->name(); }
+
+ void reseed() { rng->reseed(192); }
+
+ int gen_random_byte() { return rng->next_byte(); }
+
+ std::string gen_random(int n)
+ {
+ std::string s(n, 0);
+ rng->randomize(reinterpret_cast<byte*>(&s[0]), n);
+ return s;
+ }
+
+ void add_entropy(const std::string& in)
+ { rng->add_entropy(reinterpret_cast<const byte*>(in.c_str()), in.length()); }
+
+ private:
+ RandomNumberGenerator* rng;
+ };
+
+class Py_Cipher
+ {
+ public:
+ Py_Cipher(std::string algo_name, std::string direction,
+ std::string key);
+
+ std::string cipher_noiv(const std::string& text);
+
+ std::string cipher(const std::string& text,
+ const std::string& iv);
+
+ std::string name() const { return algo_name; }
+ private:
+ std::string algo_name;
+ Keyed_Filter* filter;
+ Pipe pipe;
+ };
+
+std::string Py_Cipher::cipher(const std::string& input,
+ const std::string& iv_str)
+ {
+ if(iv_str.size())
+ {
+ const byte* iv_bytes = reinterpret_cast<const byte*>(iv_str.data());
+ u32bit iv_len = iv_str.size();
+ filter->set_iv(InitializationVector(iv_bytes, iv_len));
+ }
+
+ pipe.process_msg(input);
+ return pipe.read_all_as_string(Pipe::LAST_MESSAGE);
+ }
+
+// For IV-less algorithms
+std::string Py_Cipher::cipher_noiv(const std::string& input)
+ {
+ pipe.process_msg(input);
+ return pipe.read_all_as_string(Pipe::LAST_MESSAGE);
+ }
+
+Py_Cipher::Py_Cipher(std::string algo_name,
+ std::string direction,
+ std::string key_str)
+ {
+ const byte* key_bytes = reinterpret_cast<const byte*>(key_str.data());
+ u32bit key_len = key_str.size();
+
+ Cipher_Dir dir;
+
+ if(direction == "encrypt")
+ dir = ENCRYPTION;
+ else if(direction == "decrypt")
+ dir = DECRYPTION;
+ else
+ throw std::invalid_argument("Bad cipher direction " + direction);
+
+ filter = get_cipher(algo_name, dir);
+ filter->set_key(SymmetricKey(key_bytes, key_len));
+ pipe.append(filter);
+ }
+
+class Py_HashFunction
+ {
+ public:
+ Py_HashFunction(const std::string& algo_name)
+ {
+ hash = get_hash(algo_name);
+ }
+
+ ~Py_HashFunction() { delete hash; }
+
+ void update(const std::string& input)
+ {
+ hash->update(input);
+ }
+
+ std::string final()
+ {
+ std::string out(output_length(), 0);
+ hash->final(reinterpret_cast<byte*>(&out[0]));
+ return out;
+ }
+
+ std::string name() const
+ {
+ return hash->name();
+ }
+
+ u32bit output_length() const
+ {
+ return hash->OUTPUT_LENGTH;
+ }
+
+ private:
+ HashFunction* hash;
+ };
+
+class Py_MAC
+ {
+ public:
+
+ Py_MAC(const std::string& name, const std::string& key_str)
+ {
+ mac = get_mac(name);
+
+ mac->set_key(reinterpret_cast<const byte*>(key_str.data()),
+ key_str.size());
+ }
+
+ ~Py_MAC() { delete mac; }
+
+ u32bit output_length() const { return mac->OUTPUT_LENGTH; }
+
+ std::string name() const { return mac->name(); }
+
+ void update(const std::string& in) { mac->update(in); }
+
+ std::string final()
+ {
+ std::string out(output_length(), 0);
+ mac->final(reinterpret_cast<byte*>(&out[0]));
+ return out;
+ }
+ private:
+ MessageAuthenticationCode* mac;
+ };
+
+BOOST_PYTHON_MODULE(_botan)
+ {
+ python::class_<LibraryInitializer>("LibraryInitializer")
+ .def(python::init< python::optional<std::string> >());
+
+ python::class_<Python_RandomNumberGenerator>("RandomNumberGenerator")
+ .def(python::init<>())
+ .def("__str__", &Python_RandomNumberGenerator::name)
+ .def("name", &Python_RandomNumberGenerator::name)
+ .def("reseed", &Python_RandomNumberGenerator::reseed)
+ .def("add_entropy", &Python_RandomNumberGenerator::add_entropy)
+ .def("gen_random_byte", &Python_RandomNumberGenerator::gen_random_byte)
+ .def("gen_random", &Python_RandomNumberGenerator::gen_random);
+
+ python::class_<Py_Cipher, boost::noncopyable>
+ ("Cipher", python::init<std::string, std::string, std::string>())
+ .def("name", &Py_Cipher::name)
+ .def("cipher", &Py_Cipher::cipher)
+ .def("cipher", &Py_Cipher::cipher_noiv);
+
+ python::class_<Py_HashFunction, boost::noncopyable>
+ ("HashFunction", python::init<std::string>())
+ .def("update", &Py_HashFunction::update)
+ .def("final", &Py_HashFunction::final)
+ .def("name", &Py_HashFunction::name)
+ .def("output_length", &Py_HashFunction::output_length);
+
+ python::class_<Py_MAC, boost::noncopyable>
+ ("MAC", python::init<std::string, std::string>())
+ .def("update", &Py_MAC::update)
+ .def("final", &Py_MAC::final)
+ .def("name", &Py_MAC::name)
+ .def("output_length", &Py_MAC::output_length);
+
+ export_filters();
+ export_pk();
+ export_x509();
+ }
diff --git a/src/wrap/python/filter.cpp b/src/wrap/python/filter.cpp
new file mode 100644
index 000000000..a678af9e5
--- /dev/null
+++ b/src/wrap/python/filter.cpp
@@ -0,0 +1,178 @@
+/*************************************************
+* 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(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(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/src/wrap/python/pk.cpp b/src/wrap/python/pk.cpp
new file mode 100644
index 000000000..72d3294b8
--- /dev/null
+++ b/src/wrap/python/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/src/wrap/python/python_botan.h b/src/wrap/python/python_botan.h
new file mode 100644
index 000000000..18c51dbb1
--- /dev/null
+++ b/src/wrap/python/python_botan.h
@@ -0,0 +1,51 @@
+
+#ifndef BOTAN_BOOST_PYTHON_COMMON_H__
+#define BOTAN_BOOST_PYTHON_COMMON_H__
+
+#include <botan/exceptn.h>
+#include <botan/parsing.h>
+#include <botan/secmem.h>
+using namespace Botan;
+
+#include <boost/python.hpp>
+namespace python = boost::python;
+
+extern void export_filters();
+extern void export_pk();
+extern void export_x509();
+
+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/src/wrap/python/x509.cpp b/src/wrap/python/x509.cpp
new file mode 100644
index 000000000..90c2bba1c
--- /dev/null
+++ b/src/wrap/python/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));
+ }
+ }