Niculae Laurentiu
2012-11-22 15:21:05 UTC
Hi,
I'm using boost::asio::ssl and what I'm trying to achieve is to pass the SSL private key for a certificate to the boost::asio::ssl library by specifying a memory buffer that contains it instead of a path to a file containing the private key. (The private key will be read from a store (e.g. windows certificate store)).
Boost::asio::ssl doesn't provide this possiblity (the only method provided being to specify a path to the PKEY file) so I decided to extend the Asio::ssl with a custom context that provides this method.
How can I do that ?
I tried by extending the ssl classes with these:
The OpenSSL implementation extended:
class openssl_context_service_ext
: public boost::asio::ssl::detail::openssl_context_service
{
public:
typedef boost::uint8_t* pkey_buffer_t;
openssl_context_service_ext(boost::asio::io_service& io_service)
: boost::asio::ssl::detail::openssl_context_service(io_service)
{
}
public:
boost::system::error_code use_private_key(impl_type& impl,
pkey_buffer_t pkey, boost::system::error_code& ec)
{
... calls SSL_CTX_use_PrivateKey with the provided key buffer
}
};
A new context service that uses this implementation:
class context_service_ext
: public boost::asio::detail::service_base<context_service_ext>
{
private:
// The type of the platform-specific implementation.
typedef detail::openssl_context_service_ext service_impl_type;
public:
typedef service_impl_type::impl_type impl_type;
explicit context_service_ext(boost::asio::io_service& io_service)
: boost::asio::detail::service_base<context_service_ext>(io_service),
service_impl_(boost::asio::use_service<service_impl_type>(io_service))
{
}
boost::system::error_code use_private_key(impl_type& impl,
const detail::openssl_context_service_ext::pkey_buffer_t pkey,
boost::system::error_code& ec)
{
return service_impl_.use_private_key(impl, pkey, ec);
}
private:
service_impl_type& service_impl_;
};
The problem is that when I try to create a basic_context with my new context_service the compiler complains (on good reason) that:
'use_private_key' : is not a member of 'boost::asio::ssl::basic_context<Service>'
To fix it I tried to extend the boost::asio::ssl::basic_context with the missing method, only that I don't have access to the private implementation (the context_service_ext) in the basic_context and there is no method provided to access it.
The basic_context extended:
template <typename Service>
class basic_context_ext
: public basic_context<Service>
{
public:
basic_context_ext(io_service& io_service, method m)
: basic_context<Service>(io_service, m)
{
}
public:
void use_private_key(const detail::openssl_context_service_ext::pkey_buffer_t pkey)
{
boost::system::error_code ec;
service_.use_private_key(impl_, pkey, ec);
boost::asio::detail::throw_error(ec);
}
};
Is it even possible to achieve what I want ? Is there another way to add this new functionality ? Is there a reason why it wasn't provided in the current implementation of boost::asio::ssl ?
Thank you!
I'm using boost::asio::ssl and what I'm trying to achieve is to pass the SSL private key for a certificate to the boost::asio::ssl library by specifying a memory buffer that contains it instead of a path to a file containing the private key. (The private key will be read from a store (e.g. windows certificate store)).
Boost::asio::ssl doesn't provide this possiblity (the only method provided being to specify a path to the PKEY file) so I decided to extend the Asio::ssl with a custom context that provides this method.
How can I do that ?
I tried by extending the ssl classes with these:
The OpenSSL implementation extended:
class openssl_context_service_ext
: public boost::asio::ssl::detail::openssl_context_service
{
public:
typedef boost::uint8_t* pkey_buffer_t;
openssl_context_service_ext(boost::asio::io_service& io_service)
: boost::asio::ssl::detail::openssl_context_service(io_service)
{
}
public:
boost::system::error_code use_private_key(impl_type& impl,
pkey_buffer_t pkey, boost::system::error_code& ec)
{
... calls SSL_CTX_use_PrivateKey with the provided key buffer
}
};
A new context service that uses this implementation:
class context_service_ext
: public boost::asio::detail::service_base<context_service_ext>
{
private:
// The type of the platform-specific implementation.
typedef detail::openssl_context_service_ext service_impl_type;
public:
typedef service_impl_type::impl_type impl_type;
explicit context_service_ext(boost::asio::io_service& io_service)
: boost::asio::detail::service_base<context_service_ext>(io_service),
service_impl_(boost::asio::use_service<service_impl_type>(io_service))
{
}
boost::system::error_code use_private_key(impl_type& impl,
const detail::openssl_context_service_ext::pkey_buffer_t pkey,
boost::system::error_code& ec)
{
return service_impl_.use_private_key(impl, pkey, ec);
}
private:
service_impl_type& service_impl_;
};
The problem is that when I try to create a basic_context with my new context_service the compiler complains (on good reason) that:
'use_private_key' : is not a member of 'boost::asio::ssl::basic_context<Service>'
To fix it I tried to extend the boost::asio::ssl::basic_context with the missing method, only that I don't have access to the private implementation (the context_service_ext) in the basic_context and there is no method provided to access it.
The basic_context extended:
template <typename Service>
class basic_context_ext
: public basic_context<Service>
{
public:
basic_context_ext(io_service& io_service, method m)
: basic_context<Service>(io_service, m)
{
}
public:
void use_private_key(const detail::openssl_context_service_ext::pkey_buffer_t pkey)
{
boost::system::error_code ec;
service_.use_private_key(impl_, pkey, ec);
boost::asio::detail::throw_error(ec);
}
};
Is it even possible to achieve what I want ? Is there another way to add this new functionality ? Is there a reason why it wasn't provided in the current implementation of boost::asio::ssl ?
Thank you!