diff options
author | Jay Berkenbilt <ejb@ql.org> | 2021-11-04 22:21:34 +0100 |
---|---|---|
committer | Jay Berkenbilt <ejb@ql.org> | 2021-11-04 23:24:54 +0100 |
commit | 3794f8e2ad536db93ce780ae11f55d86a683c536 (patch) | |
tree | b7d3568d3fccfb24b7f126b135d4cd4fc6a4d726 | |
parent | 043779187e8050673078683492dd9cbe33474cb7 (diff) | |
download | qpdf-3794f8e2ad536db93ce780ae11f55d86a683c536.tar.zst |
Support OpenSSL 3 (fixes #568)
-rw-r--r-- | ChangeLog | 15 | ||||
-rw-r--r-- | libqpdf/QPDFCrypto_openssl.cc | 61 | ||||
-rw-r--r-- | libqpdf/qpdf/QPDFCrypto_openssl.hh | 18 |
3 files changed, 89 insertions, 5 deletions
@@ -1,5 +1,20 @@ 2021-11-04 Jay Berkenbilt <ejb@ql.org> + * Add support for OpenSSL 3. Fixes #568. + + The OpenSSL version is detected at compile-time. If you want to + build with OpenSSL 3 on a system that has OpenSSL 1 installed, you + can run configure like this (or similar to this depending on how + you installed openssl3): + + pc_openssl_CFLAGS=-I/path/to/openssl3/include \ + pc_openssl_LIBS='-L/path/to/openssl3/lib64 -lssl -lcrypto' \ + ./configure + + where /path/to/openssl3 is wherever your OpenSSL 3 distribution is + installed. You may also need to set the LD_LIBRARY_PATH + environment variable if it's not installed in a standard location. + * Add range check in QPDFNumberTreeObjectHelper (fuzz issue 37740). * Add QIntC::range_check_substract to do range checking on diff --git a/libqpdf/QPDFCrypto_openssl.cc b/libqpdf/QPDFCrypto_openssl.cc index 358040d5..427ce5bb 100644 --- a/libqpdf/QPDFCrypto_openssl.cc +++ b/libqpdf/QPDFCrypto_openssl.cc @@ -4,11 +4,20 @@ #include <stdexcept> #include <string> +#if (defined(__GNUC__) || defined(__clang__)) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wold-style-cast" +#endif #include <openssl/err.h> +#ifndef QPDF_OPENSSL_1 +# include <openssl/provider.h> +#endif +#if (defined(__GNUC__) || defined(__clang__)) +# pragma GCC diagnostic pop +#endif #include <qpdf/QIntC.hh> - static void bad_bits(int bits) { @@ -33,8 +42,35 @@ check_openssl(int status) } QPDFCrypto_openssl::QPDFCrypto_openssl() : - md_ctx(EVP_MD_CTX_new()), cipher_ctx(EVP_CIPHER_CTX_new()) +#ifdef QPDF_OPENSSL_1 + rc4(EVP_rc4()), +#endif + md_ctx(EVP_MD_CTX_new()), + cipher_ctx(EVP_CIPHER_CTX_new()) { +#ifndef QPDF_OPENSSL_1 + libctx = OSSL_LIB_CTX_new(); + if (libctx == nullptr) + { + throw std::runtime_error("unable to create openssl library context"); + return; + } + legacy = OSSL_PROVIDER_load(libctx, "legacy"); + if (legacy == nullptr) + { + OSSL_LIB_CTX_free(libctx); + throw std::runtime_error("unable to load openssl legacy provider"); + return; + } + rc4 = EVP_CIPHER_fetch(libctx, "RC4", nullptr); + if (rc4 == nullptr) + { + OSSL_PROVIDER_unload(legacy); + OSSL_LIB_CTX_free(libctx); + throw std::runtime_error("unable to load openssl rc4 algorithm"); + return; + } +#endif memset(md_out, 0, sizeof(md_out)); EVP_MD_CTX_init(md_ctx); EVP_CIPHER_CTX_init(cipher_ctx); @@ -45,6 +81,11 @@ QPDFCrypto_openssl::~QPDFCrypto_openssl() EVP_MD_CTX_reset(md_ctx); EVP_CIPHER_CTX_reset(cipher_ctx); EVP_CIPHER_CTX_free(cipher_ctx); +#ifndef QPDF_OPENSSL_1 + EVP_CIPHER_free(rc4); + OSSL_PROVIDER_unload(legacy); + OSSL_LIB_CTX_free(libctx); +#endif EVP_MD_CTX_free(md_ctx); } @@ -100,7 +141,12 @@ QPDFCrypto_openssl::SHA2_update(unsigned char const* data, size_t len) void QPDFCrypto_openssl::MD5_finalize() { - if (EVP_MD_CTX_md(md_ctx)) +#ifdef QPDF_OPENSSL_1 + auto md = EVP_MD_CTX_md(md_ctx); +#else + auto md = EVP_MD_CTX_get0_md(md_ctx); +#endif + if (md) { check_openssl(EVP_DigestFinal(md_ctx, md_out + 0, nullptr)); } @@ -109,7 +155,12 @@ QPDFCrypto_openssl::MD5_finalize() void QPDFCrypto_openssl::SHA2_finalize() { - if (EVP_MD_CTX_md(md_ctx)) +#ifdef QPDF_OPENSSL_1 + auto md = EVP_MD_CTX_md(md_ctx); +#else + auto md = EVP_MD_CTX_get0_md(md_ctx); +#endif + if (md) { check_openssl(EVP_DigestFinal(md_ctx, md_out + 0, nullptr)); } @@ -137,7 +188,7 @@ QPDFCrypto_openssl::RC4_init(unsigned char const* key_data, int key_len) strlen(reinterpret_cast<const char*>(key_data))); } check_openssl( - EVP_EncryptInit_ex(cipher_ctx, EVP_rc4(), nullptr, nullptr, nullptr)); + EVP_EncryptInit_ex(cipher_ctx, rc4, nullptr, nullptr, nullptr)); check_openssl(EVP_CIPHER_CTX_set_key_length(cipher_ctx, key_len)); check_openssl( EVP_EncryptInit_ex(cipher_ctx, nullptr, nullptr, key_data, nullptr)); diff --git a/libqpdf/qpdf/QPDFCrypto_openssl.hh b/libqpdf/qpdf/QPDFCrypto_openssl.hh index 58f54c3f..eb369c8a 100644 --- a/libqpdf/qpdf/QPDFCrypto_openssl.hh +++ b/libqpdf/qpdf/QPDFCrypto_openssl.hh @@ -3,6 +3,14 @@ #include <qpdf/QPDFCryptoImpl.hh> #include <string> +#if (defined(__GNUC__) || defined(__clang__)) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wold-style-cast" +#endif +#include <openssl/opensslv.h> +#if !defined(OPENSSL_VERSION_MAJOR) || OPENSSL_VERSION_MAJOR < 3 +# define QPDF_OPENSSL_1 +#endif #include <openssl/rand.h> #ifdef OPENSSL_IS_BORINGSSL #include <openssl/cipher.h> @@ -10,6 +18,9 @@ #else #include <openssl/evp.h> #endif +#if (defined(__GNUC__) || defined(__clang__)) +# pragma GCC diagnostic pop +#endif class QPDFCrypto_openssl: public QPDFCryptoImpl { @@ -44,6 +55,13 @@ class QPDFCrypto_openssl: public QPDFCryptoImpl void rijndael_finalize() override; private: +#ifdef QPDF_OPENSSL_1 + EVP_CIPHER const* rc4; +#else + OSSL_LIB_CTX* libctx; + OSSL_PROVIDER* legacy; + EVP_CIPHER* rc4; +#endif EVP_MD_CTX* const md_ctx; EVP_CIPHER_CTX* const cipher_ctx; uint8_t md_out[EVP_MAX_MD_SIZE]; |