Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #116: Enables ECDHE temporary parameters in ASIO SSL #117

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions asio/include/asio/ssl/context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,37 @@ class context
ASIO_DECL ASIO_SYNC_OP_VOID use_tmp_dh_file(
const std::string& filename, asio::error_code& ec);

/// Use the specified certificate to obtain temporary Diffie-Hellman parameters
/// for Elliptic Curve Diffie-Hellman.
/**
* This function is used to load Elliptic Curve Diffie-Hellman parameters into
* the context from a certificate based on Elliptic Curve Cryptography (ECC).
*
* @param certificate The name of the file containing the ECC-based certificate.
* The file must use the PEM format.
*
* @param ec Set to indicate what error occurred, if any.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is copy/pasted from the other signature. Should be removed from here.

*
* @note Calls @c SSL_CTX_set_tmp_ecdh.
*/
ASIO_DECL void use_tmp_ecdh_file(const std::string& certificate);

/// Use the specified certificate to obtain temporary Diffie-Hellman parameters
/// for Elliptic Curve Diffie-Hellman.
/**
* This function is used to load Elliptic Curve Diffie-Hellman parameters into
* the context from a certificate based on Elliptic Curve Cryptography (ECC).
*
* @param certificate The name of the file containing the ECC-based certificate.
* The file must use the PEM format.
*
* @param ec Set to indicate what error occurred, if any.
*
* @note Calls @c SSL_CTX_set_tmp_ecdh.
*/
ASIO_DECL ASIO_SYNC_OP_VOID use_tmp_ecdh_file(
const std::string& certificate, asio::error_code& ec);

/// Set the password callback.
/**
* This function is used to specify a callback function to obtain password
Expand Down Expand Up @@ -714,6 +745,7 @@ class context
struct evp_pkey_cleanup;
struct rsa_cleanup;
struct dh_cleanup;
struct ec_key_cleanup;

// Helper function used to set a peer certificate verification callback.
ASIO_DECL ASIO_SYNC_OP_VOID do_set_verify_callback(
Expand All @@ -735,6 +767,10 @@ class context
ASIO_DECL ASIO_SYNC_OP_VOID do_use_tmp_dh(
BIO* bio, asio::error_code& ec);

// Helper function to set the temporary ECC Diffie-Hellman parameters from a BIO.
ASIO_DECL ASIO_SYNC_OP_VOID do_use_tmp_ecdh(
BIO* bio, asio::error_code& ec);

// Helper function to make a BIO from a memory buffer.
ASIO_DECL BIO* make_buffer_bio(const const_buffer& b);

Expand Down
69 changes: 69 additions & 0 deletions asio/include/asio/ssl/impl/context.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ struct context::dh_cleanup
~dh_cleanup() { if (p) ::DH_free(p); }
};

struct context::ec_key_cleanup
{
EC_KEY *p;
~ec_key_cleanup() { if (p) ::EC_KEY_free(p); }
};

context::context(context::method m)
: handle_(0)
{
Expand Down Expand Up @@ -1096,6 +1102,69 @@ ASIO_SYNC_OP_VOID context::do_use_tmp_dh(
ASIO_SYNC_OP_VOID_RETURN(ec);
}

void context::use_tmp_ecdh_file(const std::string& certificate)
{
asio::error_code ec;
use_tmp_ecdh_file(certificate, ec);
asio::detail::throw_error(ec, "use_tmp_ecdh_file");
}

ASIO_SYNC_OP_VOID context::use_tmp_ecdh_file(const std::string& certificate,
asio::error_code& ec)
{
::ERR_clear_error();

bio_cleanup bio = { ::BIO_new_file(certificate.c_str(), "r") };
if (bio.p)
{
return do_use_tmp_ecdh(bio.p,ec);
}

ec = asio::error_code(
static_cast<int>(::ERR_get_error()),
asio::error::get_ssl_category());
ASIO_SYNC_OP_VOID_RETURN(ec);
}

ASIO_SYNC_OP_VOID context::do_use_tmp_ecdh(
BIO* bio, asio::error_code& ec)
{
::ERR_clear_error();

int nid = NID_undef;

x509_cleanup x509 = { ::PEM_read_bio_X509(bio, NULL, 0, NULL) };
if (x509.p)
{
evp_pkey_cleanup pkey = { ::X509_get_pubkey(x509.p) };
if(pkey.p)
{
ec_key_cleanup tmp = { ::EVP_PKEY_get1_EC_KEY(pkey.p) };
if(tmp.p)
{
const EC_GROUP *group = EC_KEY_get0_group(tmp.p);
nid = EC_GROUP_get_curve_name(group);
}
}
}

ec_key_cleanup ec_key = { ::EC_KEY_new_by_curve_name(nid) };
if(ec_key.p)
{
if (::SSL_CTX_set_tmp_ecdh(handle_, ec_key.p) == 1 )
{
ec = asio::error_code();
ASIO_SYNC_OP_VOID_RETURN(ec);
}
}

ec = asio::error_code(
static_cast<int>(::ERR_get_error()),
asio::error::get_ssl_category());
ASIO_SYNC_OP_VOID_RETURN(ec);
}


ASIO_SYNC_OP_VOID context::do_set_verify_callback(
detail::verify_callback_base* callback, asio::error_code& ec)
{
Expand Down