Skip to content

Commit aac4b62

Browse files
Add helpers to some crypto APIs that vary by version (#256)
Hides API changes between older OpenSSL versions behind a helper function to improve readability and maintainability of the application code.
1 parent bdc1a07 commit aac4b62

File tree

1 file changed

+42
-60
lines changed

1 file changed

+42
-60
lines changed

include/jwt-cpp/jwt.h

Lines changed: 42 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ namespace jwt {
398398
constexpr evp_pkey_handle() noexcept = default;
399399
#ifdef JWT_OPENSSL_1_0_0
400400
/**
401-
* \brief Contruct a new handle. The handle takes ownership of the key.
401+
* \brief Construct a new handle. The handle takes ownership of the key.
402402
* \param key The key to store
403403
*/
404404
explicit evp_pkey_handle(EVP_PKEY* key) { m_key = std::shared_ptr<EVP_PKEY>(key, EVP_PKEY_free); }
@@ -411,7 +411,7 @@ namespace jwt {
411411
std::shared_ptr<EVP_PKEY> m_key{nullptr};
412412
#else
413413
/**
414-
* \brief Contruct a new handle. The handle takes ownership of the key.
414+
* \brief Construct a new handle. The handle takes ownership of the key.
415415
* \param key The key to store
416416
*/
417417
explicit constexpr evp_pkey_handle(EVP_PKEY* key) noexcept : m_key{key} {}
@@ -463,24 +463,42 @@ namespace jwt {
463463
}
464464
#endif
465465
};
466+
467+
inline std::unique_ptr<BIO, decltype(&BIO_free_all)> make_mem_buf_bio() {
468+
return std::unique_ptr<BIO, decltype(&BIO_free_all)>(BIO_new(BIO_s_mem()), BIO_free_all);
469+
}
470+
471+
inline std::unique_ptr<BIO, decltype(&BIO_free_all)> make_mem_buf_bio(const std::string& data) {
472+
return std::unique_ptr<BIO, decltype(&BIO_free_all)>(
473+
#if OPENSSL_VERSION_NUMBER <= 0x10100003L
474+
BIO_new_mem_buf(const_cast<char*>(data.data()), static_cast<int>(data.size())), BIO_free_all
475+
#else
476+
BIO_new_mem_buf(data.data(), static_cast<int>(data.size())), BIO_free_all
477+
#endif
478+
);
479+
}
480+
481+
inline std::unique_ptr<EVP_MD_CTX, void (*)(EVP_MD_CTX*)> make_evp_md_ctx() {
482+
return
483+
#ifdef JWT_OPENSSL_1_0_0
484+
std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_destroy)>(EVP_MD_CTX_create(), &EVP_MD_CTX_destroy);
485+
#else
486+
std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_free)>(EVP_MD_CTX_new(), &EVP_MD_CTX_free);
487+
#endif
488+
}
489+
466490
/**
467491
* \brief Extract the public key of a pem certificate
468492
*
469493
* \param certstr String containing the certificate encoded as pem
470494
* \param pw Password used to decrypt certificate (leave empty if not encrypted)
471-
* \param ec error_code for error_detection (gets cleared if no error occures)
495+
* \param ec error_code for error_detection (gets cleared if no error ocurred)
472496
*/
473497
inline std::string extract_pubkey_from_cert(const std::string& certstr, const std::string& pw,
474498
std::error_code& ec) {
475499
ec.clear();
476-
#if OPENSSL_VERSION_NUMBER <= 0x10100003L
477-
std::unique_ptr<BIO, decltype(&BIO_free_all)> certbio(
478-
BIO_new_mem_buf(const_cast<char*>(certstr.data()), static_cast<int>(certstr.size())), BIO_free_all);
479-
#else
480-
std::unique_ptr<BIO, decltype(&BIO_free_all)> certbio(
481-
BIO_new_mem_buf(certstr.data(), static_cast<int>(certstr.size())), BIO_free_all);
482-
#endif
483-
std::unique_ptr<BIO, decltype(&BIO_free_all)> keybio(BIO_new(BIO_s_mem()), BIO_free_all);
500+
auto certbio = make_mem_buf_bio(certstr);
501+
auto keybio = make_mem_buf_bio();
484502
if (!certbio || !keybio) {
485503
ec = error::rsa_error::create_mem_bio_failed;
486504
return {};
@@ -547,7 +565,7 @@ namespace jwt {
547565

548566
std::unique_ptr<X509, decltype(&X509_free)> cert(
549567
d2i_X509(NULL, &c_str, static_cast<int>(decodedStr.size())), X509_free);
550-
std::unique_ptr<BIO, decltype(&BIO_free_all)> certbio(BIO_new(BIO_s_mem()), BIO_free_all);
568+
auto certbio = make_mem_buf_bio();
551569
if (!cert || !certbio) {
552570
ec = error::rsa_error::create_mem_bio_failed;
553571
return {};
@@ -634,7 +652,7 @@ namespace jwt {
634652
inline evp_pkey_handle load_public_key_from_string(const std::string& key, const std::string& password,
635653
std::error_code& ec) {
636654
ec.clear();
637-
std::unique_ptr<BIO, decltype(&BIO_free_all)> pubkey_bio(BIO_new(BIO_s_mem()), BIO_free_all);
655+
auto pubkey_bio = make_mem_buf_bio();
638656
if (!pubkey_bio) {
639657
ec = error::rsa_error::create_mem_bio_failed;
640658
return {};
@@ -687,7 +705,7 @@ namespace jwt {
687705
*/
688706
inline evp_pkey_handle load_private_key_from_string(const std::string& key, const std::string& password,
689707
std::error_code& ec) {
690-
std::unique_ptr<BIO, decltype(&BIO_free_all)> privkey_bio(BIO_new(BIO_s_mem()), BIO_free_all);
708+
auto privkey_bio = make_mem_buf_bio();
691709
if (!privkey_bio) {
692710
ec = error::rsa_error::create_mem_bio_failed;
693711
return {};
@@ -729,7 +747,7 @@ namespace jwt {
729747
inline evp_pkey_handle load_public_ec_key_from_string(const std::string& key, const std::string& password,
730748
std::error_code& ec) {
731749
ec.clear();
732-
std::unique_ptr<BIO, decltype(&BIO_free_all)> pubkey_bio(BIO_new(BIO_s_mem()), BIO_free_all);
750+
auto pubkey_bio = make_mem_buf_bio();
733751
if (!pubkey_bio) {
734752
ec = error::ecdsa_error::create_mem_bio_failed;
735753
return {};
@@ -783,7 +801,7 @@ namespace jwt {
783801
*/
784802
inline evp_pkey_handle load_private_ec_key_from_string(const std::string& key, const std::string& password,
785803
std::error_code& ec) {
786-
std::unique_ptr<BIO, decltype(&BIO_free_all)> privkey_bio(BIO_new(BIO_s_mem()), BIO_free_all);
804+
auto privkey_bio = make_mem_buf_bio();
787805
if (!privkey_bio) {
788806
ec = error::ecdsa_error::create_mem_bio_failed;
789807
return {};
@@ -978,11 +996,7 @@ namespace jwt {
978996
*/
979997
std::string sign(const std::string& data, std::error_code& ec) const {
980998
ec.clear();
981-
#ifdef JWT_OPENSSL_1_0_0
982-
std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_destroy)> ctx(EVP_MD_CTX_create(), EVP_MD_CTX_destroy);
983-
#else
984-
std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_free)> ctx(EVP_MD_CTX_create(), EVP_MD_CTX_free);
985-
#endif
999+
auto ctx = helper::make_evp_md_ctx();
9861000
if (!ctx) {
9871001
ec = error::signature_generation_error::create_context_failed;
9881002
return {};
@@ -1015,11 +1029,7 @@ namespace jwt {
10151029
*/
10161030
void verify(const std::string& data, const std::string& signature, std::error_code& ec) const {
10171031
ec.clear();
1018-
#ifdef JWT_OPENSSL_1_0_0
1019-
std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_destroy)> ctx(EVP_MD_CTX_create(), EVP_MD_CTX_destroy);
1020-
#else
1021-
std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_free)> ctx(EVP_MD_CTX_create(), EVP_MD_CTX_free);
1022-
#endif
1032+
auto ctx = helper::make_evp_md_ctx();
10231033
if (!ctx) {
10241034
ec = error::signature_verification_error::create_context_failed;
10251035
return;
@@ -1095,11 +1105,7 @@ namespace jwt {
10951105
*/
10961106
std::string sign(const std::string& data, std::error_code& ec) const {
10971107
ec.clear();
1098-
#ifdef JWT_OPENSSL_1_0_0
1099-
std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_destroy)> ctx(EVP_MD_CTX_create(), EVP_MD_CTX_destroy);
1100-
#else
1101-
std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_free)> ctx(EVP_MD_CTX_create(), EVP_MD_CTX_free);
1102-
#endif
1108+
auto ctx = helper::make_evp_md_ctx();
11031109
if (!ctx) {
11041110
ec = error::signature_generation_error::create_context_failed;
11051111
return {};
@@ -1139,11 +1145,7 @@ namespace jwt {
11391145
std::string der_signature = p1363_to_der_signature(signature, ec);
11401146
if (ec) { return; }
11411147

1142-
#ifdef JWT_OPENSSL_1_0_0
1143-
std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_destroy)> ctx(EVP_MD_CTX_create(), EVP_MD_CTX_destroy);
1144-
#else
1145-
std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_free)> ctx(EVP_MD_CTX_create(), EVP_MD_CTX_free);
1146-
#endif
1148+
auto ctx = helper::make_evp_md_ctx();
11471149
if (!ctx) {
11481150
ec = error::signature_verification_error::create_context_failed;
11491151
return;
@@ -1322,12 +1324,7 @@ namespace jwt {
13221324
*/
13231325
std::string sign(const std::string& data, std::error_code& ec) const {
13241326
ec.clear();
1325-
#ifdef JWT_OPENSSL_1_0_0
1326-
std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_destroy)> ctx(EVP_MD_CTX_create(),
1327-
&EVP_MD_CTX_destroy);
1328-
#else
1329-
std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_free)> ctx(EVP_MD_CTX_new(), EVP_MD_CTX_free);
1330-
#endif
1327+
auto ctx = helper::make_evp_md_ctx();
13311328
if (!ctx) {
13321329
ec = error::signature_generation_error::create_context_failed;
13331330
return {};
@@ -1375,12 +1372,7 @@ namespace jwt {
13751372
*/
13761373
void verify(const std::string& data, const std::string& signature, std::error_code& ec) const {
13771374
ec.clear();
1378-
#ifdef JWT_OPENSSL_1_0_0
1379-
std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_destroy)> ctx(EVP_MD_CTX_create(),
1380-
&EVP_MD_CTX_destroy);
1381-
#else
1382-
std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_free)> ctx(EVP_MD_CTX_new(), EVP_MD_CTX_free);
1383-
#endif
1375+
auto ctx = helper::make_evp_md_ctx();
13841376
if (!ctx) {
13851377
ec = error::signature_verification_error::create_context_failed;
13861378
return;
@@ -1458,12 +1450,7 @@ namespace jwt {
14581450
*/
14591451
std::string sign(const std::string& data, std::error_code& ec) const {
14601452
ec.clear();
1461-
#ifdef JWT_OPENSSL_1_0_0
1462-
std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_destroy)> md_ctx(EVP_MD_CTX_create(),
1463-
&EVP_MD_CTX_destroy);
1464-
#else
1465-
std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_free)> md_ctx(EVP_MD_CTX_new(), EVP_MD_CTX_free);
1466-
#endif
1453+
auto md_ctx = helper::make_evp_md_ctx();
14671454
if (!md_ctx) {
14681455
ec = error::signature_generation_error::create_context_failed;
14691456
return {};
@@ -1512,12 +1499,7 @@ namespace jwt {
15121499
void verify(const std::string& data, const std::string& signature, std::error_code& ec) const {
15131500
ec.clear();
15141501

1515-
#ifdef JWT_OPENSSL_1_0_0
1516-
std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_destroy)> md_ctx(EVP_MD_CTX_create(),
1517-
&EVP_MD_CTX_destroy);
1518-
#else
1519-
std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_free)> md_ctx(EVP_MD_CTX_new(), EVP_MD_CTX_free);
1520-
#endif
1502+
auto md_ctx = helper::make_evp_md_ctx();
15211503
if (!md_ctx) {
15221504
ec = error::signature_verification_error::create_context_failed;
15231505
return;

0 commit comments

Comments
 (0)