Skip to content

Commit

Permalink
Rearrange to provide a better structure that makes it earlier to review
Browse files Browse the repository at this point in the history
  • Loading branch information
lo-simon committed Mar 7, 2024
1 parent 69b4cee commit aa278cb
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 33 deletions.
45 changes: 28 additions & 17 deletions Development/boost/asio/ssl/use_tmp_ecdh.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,26 +57,49 @@ inline
BOOST_ASIO_SYNC_OP_VOID do_use_tmp_ecdh(boost::asio::ssl::context& ctx,
BIO* bio, boost::system::error_code& ec)
{
#if OPENSSL_VERSION_NUMBER < 0x30000000L
::ERR_clear_error();

#if OPENSSL_VERSION_NUMBER < 0x30000000L
int nid = NID_undef;
#endif

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)
{
#if OPENSSL_VERSION_NUMBER < 0x30000000L
ec_key_cleanup key = { ::EVP_PKEY_get1_EC_KEY(pkey.p) };
if (key.p)
{
const EC_GROUP *group = EC_KEY_get0_group(key.p);
const EC_GROUP* group = EC_KEY_get0_group(key.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(ctx.native_handle(), ec_key.p) == 1)
{
ec = boost::system::error_code();
BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
}

ec = boost::system::error_code(
static_cast<int>(::ERR_get_error()),
boost::asio::error::get_ssl_category());
BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
#else
::ERR_clear_error();

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)
{
char curve_name[64];
size_t return_size{ 0 };
if (::EVP_PKEY_get_utf8_string_param(pkey.p, OSSL_PKEY_PARAM_GROUP_NAME, curve_name, sizeof(curve_name), &return_size))
Expand All @@ -87,26 +110,14 @@ BOOST_ASIO_SYNC_OP_VOID do_use_tmp_ecdh(boost::asio::ssl::context& ctx,
BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
}
#endif
}
}

#if OPENSSL_VERSION_NUMBER < 0x30000000L
ec_key_cleanup ec_key = { ::EC_KEY_new_by_curve_name(nid) };
if (ec_key.p)
{
if (::SSL_CTX_set_tmp_ecdh(ctx.native_handle(), ec_key.p) == 1)
{
ec = boost::system::error_code();
BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
}
#endif

ec = boost::system::error_code(
static_cast<int>(::ERR_get_error()),
boost::asio::error::get_ssl_category());
BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
#endif
}

inline
Expand Down
106 changes: 90 additions & 16 deletions Development/nmos/jwk_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,13 @@ namespace nmos
// convert JSON Web Key to RSA Public Key
// The "n" (modulus) parameter contains the modulus value for the RSA public key
// It is represented as a Base64urlUInt - encoded value
// The "e" (exponent)parameter contains the exponent value for the RSA public key
// The "e" (exponent) parameter contains the exponent value for the RSA public key
// It is represented as a Base64urlUInt - encoded value
// see https://tools.ietf.org/html/rfc7518#section-6.3.1
// this function is based on https://stackoverflow.com/questions/57217529/how-to-convert-jwk-public-key-to-pem-format-in-c
utility::string_t jwk_to_rsa_public_key(const utility::string_t& base64_n, const utility::string_t& base64_e)
{
#if OPENSSL_VERSION_NUMBER < 0x30000000L
using ssl::experimental::BIO_ptr;

auto n = utility::conversions::from_base64url(base64_n);
Expand All @@ -84,9 +85,6 @@ namespace nmos
BIGNUM_ptr modulus(BN_bin2bn(n.data(), (int)n.size(), NULL), &BN_free);
BIGNUM_ptr exponent(BN_bin2bn(e.data(), (int)e.size(), NULL), &BN_free);

EVP_PKEY* pkey = NULL;

#if OPENSSL_VERSION_NUMBER < 0x30000000L
RSA_ptr rsa(RSA_new(), &RSA_free);
if (!rsa)
{
Expand All @@ -106,7 +104,33 @@ namespace nmos
{
throw jwk_exception("convert jwk to pem error: failed to initialise RSA");
}

BIO_ptr bio(BIO_new(BIO_s_mem()), &BIO_free);
if (!bio)
{
throw jwk_exception("convert jwk to pem error: failed to create BIO memory");
}
if (PEM_write_bio_RSA_PUBKEY(bio.get(), rsa.get()))
{
BUF_MEM* buf;
BIO_get_mem_ptr(bio.get(), &buf);
std::string pem(size_t(buf->length), 0);
BIO_read(bio.get(), (void*)pem.data(), (int)pem.length());
return utility::s2us(pem);
}
else
{
throw jwk_exception("convert jwk to pem error: failed to write RSA public key to BIO memory");
}
#else
using ssl::experimental::BIO_ptr;

auto n = utility::conversions::from_base64url(base64_n);
auto e = utility::conversions::from_base64url(base64_e);

BIGNUM_ptr modulus(BN_bin2bn(n.data(), (int)n.size(), NULL), &BN_free);
BIGNUM_ptr exponent(BN_bin2bn(e.data(), (int)e.size(), NULL), &BN_free);

OSSL_PARAM_BLD_ptr param_bld(OSSL_PARAM_BLD_new(), &OSSL_PARAM_BLD_free);
if (OSSL_PARAM_BLD_push_BN(param_bld.get(), OSSL_PKEY_PARAM_RSA_N, modulus.get()))
{
Expand All @@ -120,23 +144,19 @@ namespace nmos
OSSL_PARAM_ptr params(OSSL_PARAM_BLD_to_param(param_bld.get()), &OSSL_PARAM_free);
EVP_PKEY_CTX_ptr ctx(EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL), &EVP_PKEY_CTX_free);

EVP_PKEY* pkey = NULL;
if ((1 != EVP_PKEY_fromdata_init(ctx.get())) || (1 != EVP_PKEY_fromdata(ctx.get(), &pkey, EVP_PKEY_PUBLIC_KEY, params.get())))
{
throw jwk_exception("convert jwk to pem error: failed to create EVP_PKEY-RSA public key from OSSL parameters");
}
#endif

BIO_ptr bio(BIO_new(BIO_s_mem()), &BIO_free);
if (!bio)
{
if (pkey) { EVP_PKEY_free(pkey); }
throw jwk_exception("convert jwk to pem error: failed to create BIO memory");
}
#if OPENSSL_VERSION_NUMBER < 0x30000000L
if (PEM_write_bio_RSA_PUBKEY(bio.get(), rsa.get()))
#else
if (PEM_write_bio_PUBKEY(bio.get(), pkey))
#endif
{
if (pkey) { EVP_PKEY_free(pkey); }
BUF_MEM* buf;
Expand All @@ -150,11 +170,13 @@ namespace nmos
if (pkey) { EVP_PKEY_free(pkey); }
throw jwk_exception("convert jwk to pem error: failed to write RSA public key to BIO memory");
}
#endif
}

// convert RSA to JSON Web Key
web::json::value rsa_to_jwk(const EVP_PKEY_ptr& pkey, const utility::string_t& keyid, const jwk::public_key_use& pubkey_use, const jwk::algorithm& alg)
{
#if OPENSSL_VERSION_NUMBER < 0x30000000L
auto bignum_to_string_t = [](const BIGNUM* bignum)
{
if (bignum)
Expand All @@ -169,7 +191,6 @@ namespace nmos
return utility::string_t{};
};

#if OPENSSL_VERSION_NUMBER < 0x30000000L
RSA_ptr rsa(EVP_PKEY_get1_RSA(pkey.get()), &RSA_free);

// The n, e and d parameters can be obtained by calling RSA_get0_key().
Expand All @@ -184,7 +205,32 @@ namespace nmos

const auto base64_n = bignum_to_string_t(modulus);
const auto base64_e = bignum_to_string_t(exponent);

// construct jwk
return web::json::value_of({
{ U("kid"), keyid },
{ U("kty"), U("RSA") },
{ U("n"), base64_n },
{ U("e"), base64_e },
{ U("alg"), alg.name },
{ U("use"), pubkey_use.name }
});
}
#else
auto bignum_to_string_t = [](const BIGNUM* bignum)
{
if (bignum)
{
const auto size = BN_num_bytes(bignum);
std::vector<uint8_t> data(size);
if (BN_bn2bin(bignum, data.data()))
{
return utility::conversions::to_base64url(data);
}
}
return utility::string_t{};
};

BIGNUM* modulus = nullptr;
BIGNUM* exponent = nullptr;

Expand All @@ -201,7 +247,7 @@ namespace nmos
base64_e = bignum_to_string_t(exponent);
BN_clear_free(exponent);
}
#endif

// construct jwk
return web::json::value_of({
{ U("kid"), keyid },
Expand All @@ -210,13 +256,15 @@ namespace nmos
{ U("e"), base64_e },
{ U("alg"), alg.name },
{ U("use"), pubkey_use.name }
});
});
}
#endif
}

// extract RSA public key from RSA private key
utility::string_t rsa_public_key(const utility::string_t& rsa_private_key)
{
#if OPENSSL_VERSION_NUMBER < 0x30000000L
using ssl::experimental::BIO_ptr;

const std::string private_key_buffer{ utility::us2s(rsa_private_key) };
Expand All @@ -233,21 +281,46 @@ namespace nmos
throw jwk_exception("extract public key error: failed to create EVP_PKEY-RSA from BIO private key");
}

#if OPENSSL_VERSION_NUMBER < 0x30000000L
RSA_ptr rsa(EVP_PKEY_get1_RSA(private_key.get()), &RSA_free);
if (!rsa)
{
throw jwk_exception("extract public key error: failed to load RSA key from private key");
}
#endif

BIO_ptr bio(BIO_new(BIO_s_mem()), &BIO_free);

#if OPENSSL_VERSION_NUMBER < 0x30000000L
if (bio && PEM_write_bio_RSA_PUBKEY(bio.get(), rsa.get()))
{
BUF_MEM* buf;
BIO_get_mem_ptr(bio.get(), &buf);
std::string public_key(size_t(buf->length), 0);
BIO_read(bio.get(), (void*)public_key.data(), (int)public_key.length());
return utility::s2us(public_key);
}
else
{
throw jwk_exception("extract public key error: failed to write EVP_PKEY-RSA public key to BIO memory");
}
#else
using ssl::experimental::BIO_ptr;

const std::string private_key_buffer{ utility::us2s(rsa_private_key) };
BIO_ptr private_key_bio(BIO_new_mem_buf((void*)private_key_buffer.c_str(), (int)private_key_buffer.length()), &BIO_free);
if (!private_key_bio)
{
throw jwk_exception("extract public key error: failed to create BIO memory from PEM private key");
}

EVP_PKEY_ptr private_key(PEM_read_bio_PrivateKey(private_key_bio.get(), NULL, NULL, NULL), &EVP_PKEY_free);

if (!private_key)
{
throw jwk_exception("extract public key error: failed to create EVP_PKEY-RSA from BIO private key");
}

BIO_ptr bio(BIO_new(BIO_s_mem()), &BIO_free);

if (bio && PEM_write_bio_PUBKEY(bio.get(), private_key.get()))
#endif
{
BUF_MEM* buf;
BIO_get_mem_ptr(bio.get(), &buf);
Expand All @@ -259,6 +332,7 @@ namespace nmos
{
throw jwk_exception("extract public key error: failed to write EVP_PKEY-RSA public key to BIO memory");
}
#endif
}

// convert JSON Web Key to RSA public key
Expand Down

0 comments on commit aa278cb

Please sign in to comment.