Commit 3794f8e2ad536db93ce780ae11f55d86a683c536

Authored by Jay Berkenbilt
1 parent 04377918

Support OpenSSL 3 (fixes #568)

ChangeLog
1 2021-11-04 Jay Berkenbilt <ejb@ql.org> 1 2021-11-04 Jay Berkenbilt <ejb@ql.org>
2 2
  3 + * Add support for OpenSSL 3. Fixes #568.
  4 +
  5 + The OpenSSL version is detected at compile-time. If you want to
  6 + build with OpenSSL 3 on a system that has OpenSSL 1 installed, you
  7 + can run configure like this (or similar to this depending on how
  8 + you installed openssl3):
  9 +
  10 + pc_openssl_CFLAGS=-I/path/to/openssl3/include \
  11 + pc_openssl_LIBS='-L/path/to/openssl3/lib64 -lssl -lcrypto' \
  12 + ./configure
  13 +
  14 + where /path/to/openssl3 is wherever your OpenSSL 3 distribution is
  15 + installed. You may also need to set the LD_LIBRARY_PATH
  16 + environment variable if it's not installed in a standard location.
  17 +
3 * Add range check in QPDFNumberTreeObjectHelper (fuzz issue 37740). 18 * Add range check in QPDFNumberTreeObjectHelper (fuzz issue 37740).
4 19
5 * Add QIntC::range_check_substract to do range checking on 20 * Add QIntC::range_check_substract to do range checking on
libqpdf/QPDFCrypto_openssl.cc
@@ -4,11 +4,20 @@ @@ -4,11 +4,20 @@
4 #include <stdexcept> 4 #include <stdexcept>
5 #include <string> 5 #include <string>
6 6
  7 +#if (defined(__GNUC__) || defined(__clang__))
  8 +# pragma GCC diagnostic push
  9 +# pragma GCC diagnostic ignored "-Wold-style-cast"
  10 +#endif
7 #include <openssl/err.h> 11 #include <openssl/err.h>
  12 +#ifndef QPDF_OPENSSL_1
  13 +# include <openssl/provider.h>
  14 +#endif
  15 +#if (defined(__GNUC__) || defined(__clang__))
  16 +# pragma GCC diagnostic pop
  17 +#endif
8 18
9 #include <qpdf/QIntC.hh> 19 #include <qpdf/QIntC.hh>
10 20
11 -  
12 static void 21 static void
13 bad_bits(int bits) 22 bad_bits(int bits)
14 { 23 {
@@ -33,8 +42,35 @@ check_openssl(int status) @@ -33,8 +42,35 @@ check_openssl(int status)
33 } 42 }
34 43
35 QPDFCrypto_openssl::QPDFCrypto_openssl() : 44 QPDFCrypto_openssl::QPDFCrypto_openssl() :
36 - md_ctx(EVP_MD_CTX_new()), cipher_ctx(EVP_CIPHER_CTX_new()) 45 +#ifdef QPDF_OPENSSL_1
  46 + rc4(EVP_rc4()),
  47 +#endif
  48 + md_ctx(EVP_MD_CTX_new()),
  49 + cipher_ctx(EVP_CIPHER_CTX_new())
37 { 50 {
  51 +#ifndef QPDF_OPENSSL_1
  52 + libctx = OSSL_LIB_CTX_new();
  53 + if (libctx == nullptr)
  54 + {
  55 + throw std::runtime_error("unable to create openssl library context");
  56 + return;
  57 + }
  58 + legacy = OSSL_PROVIDER_load(libctx, "legacy");
  59 + if (legacy == nullptr)
  60 + {
  61 + OSSL_LIB_CTX_free(libctx);
  62 + throw std::runtime_error("unable to load openssl legacy provider");
  63 + return;
  64 + }
  65 + rc4 = EVP_CIPHER_fetch(libctx, "RC4", nullptr);
  66 + if (rc4 == nullptr)
  67 + {
  68 + OSSL_PROVIDER_unload(legacy);
  69 + OSSL_LIB_CTX_free(libctx);
  70 + throw std::runtime_error("unable to load openssl rc4 algorithm");
  71 + return;
  72 + }
  73 +#endif
38 memset(md_out, 0, sizeof(md_out)); 74 memset(md_out, 0, sizeof(md_out));
39 EVP_MD_CTX_init(md_ctx); 75 EVP_MD_CTX_init(md_ctx);
40 EVP_CIPHER_CTX_init(cipher_ctx); 76 EVP_CIPHER_CTX_init(cipher_ctx);
@@ -45,6 +81,11 @@ QPDFCrypto_openssl::~QPDFCrypto_openssl() @@ -45,6 +81,11 @@ QPDFCrypto_openssl::~QPDFCrypto_openssl()
45 EVP_MD_CTX_reset(md_ctx); 81 EVP_MD_CTX_reset(md_ctx);
46 EVP_CIPHER_CTX_reset(cipher_ctx); 82 EVP_CIPHER_CTX_reset(cipher_ctx);
47 EVP_CIPHER_CTX_free(cipher_ctx); 83 EVP_CIPHER_CTX_free(cipher_ctx);
  84 +#ifndef QPDF_OPENSSL_1
  85 + EVP_CIPHER_free(rc4);
  86 + OSSL_PROVIDER_unload(legacy);
  87 + OSSL_LIB_CTX_free(libctx);
  88 +#endif
48 EVP_MD_CTX_free(md_ctx); 89 EVP_MD_CTX_free(md_ctx);
49 } 90 }
50 91
@@ -100,7 +141,12 @@ QPDFCrypto_openssl::SHA2_update(unsigned char const* data, size_t len) @@ -100,7 +141,12 @@ QPDFCrypto_openssl::SHA2_update(unsigned char const* data, size_t len)
100 void 141 void
101 QPDFCrypto_openssl::MD5_finalize() 142 QPDFCrypto_openssl::MD5_finalize()
102 { 143 {
103 - if (EVP_MD_CTX_md(md_ctx)) 144 +#ifdef QPDF_OPENSSL_1
  145 + auto md = EVP_MD_CTX_md(md_ctx);
  146 +#else
  147 + auto md = EVP_MD_CTX_get0_md(md_ctx);
  148 +#endif
  149 + if (md)
104 { 150 {
105 check_openssl(EVP_DigestFinal(md_ctx, md_out + 0, nullptr)); 151 check_openssl(EVP_DigestFinal(md_ctx, md_out + 0, nullptr));
106 } 152 }
@@ -109,7 +155,12 @@ QPDFCrypto_openssl::MD5_finalize() @@ -109,7 +155,12 @@ QPDFCrypto_openssl::MD5_finalize()
109 void 155 void
110 QPDFCrypto_openssl::SHA2_finalize() 156 QPDFCrypto_openssl::SHA2_finalize()
111 { 157 {
112 - if (EVP_MD_CTX_md(md_ctx)) 158 +#ifdef QPDF_OPENSSL_1
  159 + auto md = EVP_MD_CTX_md(md_ctx);
  160 +#else
  161 + auto md = EVP_MD_CTX_get0_md(md_ctx);
  162 +#endif
  163 + if (md)
113 { 164 {
114 check_openssl(EVP_DigestFinal(md_ctx, md_out + 0, nullptr)); 165 check_openssl(EVP_DigestFinal(md_ctx, md_out + 0, nullptr));
115 } 166 }
@@ -137,7 +188,7 @@ QPDFCrypto_openssl::RC4_init(unsigned char const* key_data, int key_len) @@ -137,7 +188,7 @@ QPDFCrypto_openssl::RC4_init(unsigned char const* key_data, int key_len)
137 strlen(reinterpret_cast<const char*>(key_data))); 188 strlen(reinterpret_cast<const char*>(key_data)));
138 } 189 }
139 check_openssl( 190 check_openssl(
140 - EVP_EncryptInit_ex(cipher_ctx, EVP_rc4(), nullptr, nullptr, nullptr)); 191 + EVP_EncryptInit_ex(cipher_ctx, rc4, nullptr, nullptr, nullptr));
141 check_openssl(EVP_CIPHER_CTX_set_key_length(cipher_ctx, key_len)); 192 check_openssl(EVP_CIPHER_CTX_set_key_length(cipher_ctx, key_len));
142 check_openssl( 193 check_openssl(
143 EVP_EncryptInit_ex(cipher_ctx, nullptr, nullptr, key_data, nullptr)); 194 EVP_EncryptInit_ex(cipher_ctx, nullptr, nullptr, key_data, nullptr));
libqpdf/qpdf/QPDFCrypto_openssl.hh
@@ -3,6 +3,14 @@ @@ -3,6 +3,14 @@
3 3
4 #include <qpdf/QPDFCryptoImpl.hh> 4 #include <qpdf/QPDFCryptoImpl.hh>
5 #include <string> 5 #include <string>
  6 +#if (defined(__GNUC__) || defined(__clang__))
  7 +# pragma GCC diagnostic push
  8 +# pragma GCC diagnostic ignored "-Wold-style-cast"
  9 +#endif
  10 +#include <openssl/opensslv.h>
  11 +#if !defined(OPENSSL_VERSION_MAJOR) || OPENSSL_VERSION_MAJOR < 3
  12 +# define QPDF_OPENSSL_1
  13 +#endif
6 #include <openssl/rand.h> 14 #include <openssl/rand.h>
7 #ifdef OPENSSL_IS_BORINGSSL 15 #ifdef OPENSSL_IS_BORINGSSL
8 #include <openssl/cipher.h> 16 #include <openssl/cipher.h>
@@ -10,6 +18,9 @@ @@ -10,6 +18,9 @@
10 #else 18 #else
11 #include <openssl/evp.h> 19 #include <openssl/evp.h>
12 #endif 20 #endif
  21 +#if (defined(__GNUC__) || defined(__clang__))
  22 +# pragma GCC diagnostic pop
  23 +#endif
13 24
14 class QPDFCrypto_openssl: public QPDFCryptoImpl 25 class QPDFCrypto_openssl: public QPDFCryptoImpl
15 { 26 {
@@ -44,6 +55,13 @@ class QPDFCrypto_openssl: public QPDFCryptoImpl @@ -44,6 +55,13 @@ class QPDFCrypto_openssl: public QPDFCryptoImpl
44 void rijndael_finalize() override; 55 void rijndael_finalize() override;
45 56
46 private: 57 private:
  58 +#ifdef QPDF_OPENSSL_1
  59 + EVP_CIPHER const* rc4;
  60 +#else
  61 + OSSL_LIB_CTX* libctx;
  62 + OSSL_PROVIDER* legacy;
  63 + EVP_CIPHER* rc4;
  64 +#endif
47 EVP_MD_CTX* const md_ctx; 65 EVP_MD_CTX* const md_ctx;
48 EVP_CIPHER_CTX* const cipher_ctx; 66 EVP_CIPHER_CTX* const cipher_ctx;
49 uint8_t md_out[EVP_MAX_MD_SIZE]; 67 uint8_t md_out[EVP_MAX_MD_SIZE];