File qpdf-support-openssl3.patch of Package qpdf

From 3794f8e2ad536db93ce780ae11f55d86a683c536 Mon Sep 17 00:00:00 2001
From: Jay Berkenbilt <ejb@ql.org>
Date: Thu, 4 Nov 2021 17:21:34 -0400
Subject: [PATCH] Support OpenSSL 3 (fixes #568)

---
 ChangeLog                          | 15 ++++++++
 libqpdf/QPDFCrypto_openssl.cc      | 61 +++++++++++++++++++++++++++---
 libqpdf/qpdf/QPDFCrypto_openssl.hh | 18 +++++++++
 3 files changed, 89 insertions(+), 5 deletions(-)

Index: qpdf-10.3.1/libqpdf/QPDFCrypto_openssl.cc
===================================================================
--- qpdf-10.3.1.orig/libqpdf/QPDFCrypto_openssl.cc
+++ qpdf-10.3.1/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
 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 ch
             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));
Index: qpdf-10.3.1/libqpdf/qpdf/QPDFCrypto_openssl.hh
===================================================================
--- qpdf-10.3.1.orig/libqpdf/qpdf/QPDFCrypto_openssl.hh
+++ qpdf-10.3.1/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 QPDFCry
     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];
Index: qpdf-10.3.1/ChangeLog
===================================================================
--- qpdf-10.3.1.orig/ChangeLog
+++ qpdf-10.3.1/ChangeLog
@@ -1,5 +1,20 @@
 2021-03-11  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.
+
 	* 10.3.1: release
 
 	* Bug fix: allow /DR to be direct in /AcroForm
openSUSE Build Service is sponsored by