From cbb6e6284768e9450a581037e6e01c6f7ab5018f Mon Sep 17 00:00:00 2001 From: eabdullin Date: Wed, 14 May 2025 16:07:27 +0000 Subject: [PATCH] import UBI qpdf-11.8.0-5.el10 --- .gitignore | 4 +- gating.yaml | 7 - qpdf-CVE-2018-9918.patch | 55 -- qpdf-doc.patch | 30 - qpdf-gnutls-crypto.patch | 1142 -------------------------------------- qpdf-relax.patch | 242 ++++---- qpdf.spec | 320 +++++++++-- sources | 3 +- 8 files changed, 404 insertions(+), 1399 deletions(-) delete mode 100644 gating.yaml delete mode 100644 qpdf-CVE-2018-9918.patch delete mode 100644 qpdf-doc.patch delete mode 100644 qpdf-gnutls-crypto.patch diff --git a/.gitignore b/.gitignore index 5e46ee7..bd94dfe 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ -SOURCES/qpdf-7.1.1.tar.gz -/qpdf-7.1.1.tar.gz +qpdf-11.8.0-doc.zip +qpdf-11.8.0.tar.gz diff --git a/gating.yaml b/gating.yaml deleted file mode 100644 index cf5f35b..0000000 --- a/gating.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- !Policy -product_versions: - - rhel-8 -decision_context: osci_compose_gate -rules: - - !PassingTestCaseRule {test_case_name: baseos-ci.brew-build.tier1.functional} - - !PassingTestCaseRule {test_case_name: baseos-ci.brew-build.tedude.validation} diff --git a/qpdf-CVE-2018-9918.patch b/qpdf-CVE-2018-9918.patch deleted file mode 100644 index 76f4e21..0000000 --- a/qpdf-CVE-2018-9918.patch +++ /dev/null @@ -1,55 +0,0 @@ -diff -up qpdf-7.1.1/libqpdf/QPDFObjectHandle.cc.CVE-2018-9918 qpdf-7.1.1/libqpdf/QPDFObjectHandle.cc ---- qpdf-7.1.1/libqpdf/QPDFObjectHandle.cc.CVE-2018-9918 2018-02-05 00:31:42.000000000 +0100 -+++ qpdf-7.1.1/libqpdf/QPDFObjectHandle.cc 2018-04-16 15:35:36.378343714 +0200 -@@ -1054,12 +1054,26 @@ QPDFObjectHandle::parseInternal(PointerH - - case QPDFTokenizer::tt_array_open: - case QPDFTokenizer::tt_dict_open: -- olist_stack.push_back(std::vector()); -- state = st_start; -- offset_stack.push_back(input->tell()); -- state_stack.push_back( -- (token.getType() == QPDFTokenizer::tt_array_open) ? -- st_array : st_dictionary); -+ if (olist_stack.size() > 500) -+ { -+ QTC::TC("qpdf", "QPDFObjectHandle too deep"); -+ warn(context, -+ QPDFExc(qpdf_e_damaged_pdf, input->getName(), -+ object_description, -+ input->getLastOffset(), -+ "ignoring excessively deeply nested data structure")); -+ object = newNull(); -+ state = st_top; -+ } -+ else -+ { -+ olist_stack.push_back(std::vector()); -+ state = st_start; -+ offset_stack.push_back(input->tell()); -+ state_stack.push_back( -+ (token.getType() == QPDFTokenizer::tt_array_open) ? -+ st_array : st_dictionary); -+ } - break; - - case QPDFTokenizer::tt_bool: -diff -up qpdf-7.1.1/qpdf/qpdf.testcov.CVE-2018-9918 qpdf-7.1.1/qpdf/qpdf.testcov ---- qpdf-7.1.1/qpdf/qpdf.testcov.CVE-2018-9918 2018-02-05 00:31:42.000000000 +0100 -+++ qpdf-7.1.1/qpdf/qpdf.testcov 2018-04-16 15:35:36.379343705 +0200 -@@ -302,3 +302,4 @@ qpdf-c called qpdf_set_compress_streams - qpdf-c called qpdf_set_preserve_unreferenced_objects 0 - qpdf-c called qpdf_set_newline_before_endstream 0 - QPDF_Stream TIFF predictor 0 -+QPDFObjectHandle too deep 0 -diff -up qpdf-7.1.1/qpdf/qtest/qpdf/issue-146.out.CVE-2018-9918 qpdf-7.1.1/qpdf/qtest/qpdf/issue-146.out ---- qpdf-7.1.1/qpdf/qtest/qpdf/issue-146.out.CVE-2018-9918 2018-02-05 00:31:42.000000000 +0100 -+++ qpdf-7.1.1/qpdf/qtest/qpdf/issue-146.out 2018-04-16 15:53:17.499476948 +0200 -@@ -1,5 +1,5 @@ - WARNING: issue-146.pdf: file is damaged - WARNING: issue-146.pdf: can't find startxref - WARNING: issue-146.pdf: Attempting to reconstruct cross-reference table --WARNING: issue-146.pdf (trailer, file position 20728): unknown token while reading object; treating as string --issue-146.pdf (trailer, file position 20732): EOF while reading token -+WARNING: issue-146.pdf (trailer, file position 695): ignoring excessively deeply nested data structure -+issue-146.pdf: unable to find trailer dictionary while recovering damaged file diff --git a/qpdf-doc.patch b/qpdf-doc.patch deleted file mode 100644 index 732f8f3..0000000 --- a/qpdf-doc.patch +++ /dev/null @@ -1,30 +0,0 @@ -diff -up qpdf-4.1.0/manual/fix-qdf.1.in.doc qpdf-4.1.0/manual/fix-qdf.1.in ---- qpdf-4.1.0/manual/fix-qdf.1.in.doc 2013-04-14 21:03:51.000000000 +0200 -+++ qpdf-4.1.0/manual/fix-qdf.1.in 2013-05-23 18:12:21.506581935 +0200 -@@ -14,5 +14,4 @@ the same file with stream lengths, cross - object stream offset tables regenerated. - .PP - For details about fix-qdf and about PDF files in QDF mode, please see --the qpdf manual, which can be found in @docdir@/qpdf-manual.html or --@docdir@/qpdf-manual.pdf. -+the qpdf manual, which can be found in qpdf-doc package. -diff -up qpdf-4.1.0/manual/qpdf.1.in.doc qpdf-4.1.0/manual/qpdf.1.in ---- qpdf-4.1.0/manual/qpdf.1.in.doc 2013-04-14 21:03:51.000000000 +0200 -+++ qpdf-4.1.0/manual/qpdf.1.in 2013-05-23 18:12:13.723690019 +0200 -@@ -16,4 +16,4 @@ useful primarily to PDF developers. - .PP - For a summary of qpdf's options, please run - \fBqpdf --help\fR. A complete manual can be found in --@docdir@/qpdf-manual.html or @docdir@/qpdf-manual.pdf. -+qpdf-doc package. -diff -up qpdf-4.1.0/manual/zlib-flate.1.in.doc qpdf-4.1.0/manual/zlib-flate.1.in ---- qpdf-4.1.0/manual/zlib-flate.1.in.doc 2013-04-14 21:03:51.000000000 +0200 -+++ qpdf-4.1.0/manual/zlib-flate.1.in 2013-05-23 18:12:07.571775453 +0200 -@@ -21,6 +21,6 @@ This program should not be used as a gen - tool. Use something like gzip(1) instead. - .PP - For details about qpdf, please see the qpdf manual, which can be found --in @docdir@/qpdf-manual.html or @docdir@/qpdf-manual.pdf. -+in qpdf-doc package. - .SH "SEE ALSO" - qpdf(1), gzip(1) diff --git a/qpdf-gnutls-crypto.patch b/qpdf-gnutls-crypto.patch deleted file mode 100644 index fc6cf08..0000000 --- a/qpdf-gnutls-crypto.patch +++ /dev/null @@ -1,1142 +0,0 @@ -diff --git a/configure.ac b/configure.ac -index a9f0316..6ff59ef 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -348,6 +348,36 @@ AC_ARG_ENABLE(show-failed-test-output, - fi], - [SHOW_FAILED_TEST_OUTPUT=0]) - -+AC_PATH_TOOL(PKGCONFIG, pkg-config) -+ -+AC_MSG_CHECKING(if cryptography will be supplied by GNU TLS) -+AC_ARG_ENABLE(gnutls, -+ AS_HELP_STRING([--enable-gnutls], -+ [enable cryptography by GNUTLS]), -+ [if test "$enableval" = "yes"; then -+ if test "x$PKGCONFIG" != x ; then -+ AC_TRY_COMPILE([ -+ #include ], , , AC_MSG_ERROR([GNU TLS development headers are needed.])) -+ GNUTLSFLAGS=`pkg-config --cflags gnutls` -+ GNUTLSLIBS=`pkg-config --libs gnutls` -+ LIBS="$LIBS $GNUTLSLIBS" -+ CPPFLAGS="$CPPFLAGS $GNUTLSFLAGS" -+ AC_DEFINE([HAVE_GNUTLS], [1], [If cryptography will be supplied by GNU TLS]) -+ HAVE_GNUTLS=1 -+ else -+ HAVE_GNUTLS=0 -+ AC_MSG_ERROR([pkg-config is needed to configure compilation with GNU TLS.]) -+ fi -+ else -+ HAVE_GNUTLS=0 -+ fi], -+ [HAVE_GNUTLS=0]) -+if test "$HAVE_GNUTLS" = "1" ; then -+ AC_MSG_RESULT(yes) -+else -+ AC_MSG_RESULT(no) -+fi -+ - AC_ARG_WITH(docbook-xsl, - AS_HELP_STRING([--with-docbook-xsl=DIR], - [location of docbook 4.x xml stylesheets]), -diff --git a/libqpdf/MD5-gnutls.cc b/libqpdf/MD5-gnutls.cc -new file mode 100644 -index 0000000..5611b3e ---- /dev/null -+++ b/libqpdf/MD5-gnutls.cc -@@ -0,0 +1,61 @@ -+#include -+#include -+#include -+ -+ -+// MD5 initialization. Begins an MD5 operation, writing a new context. -+void MD5::init() -+{ -+ int ret; -+ -+ ret = gnutls_hash_init(&ctx, GNUTLS_DIG_MD5); -+ if (ret < 0) { -+ QUtil::throw_system_error( -+ std::string("GNU TLS: MD5 error:") + std::string(gnutls_strerror(ret))); -+ ctx = nullptr; -+ } -+ -+ finalized = false; -+ memset(digest_val, 0, sizeof(digest_val)); -+} -+ -+// MD5 block update operation. Continues an MD5 message-digest -+// operation, processing another message block, and updating the -+// context. -+ -+void MD5::update(unsigned char *input, -+ unsigned int inputLen) -+{ -+ if (ctx != nullptr && input != nullptr) -+ gnutls_hash(ctx, input, inputLen); -+} -+ -+// MD5 finalization. Ends an MD5 message-digest operation, writing the -+// the message digest and zeroizing the context. -+void MD5::final() -+{ -+ if (finalized) -+ return; -+ -+ if (ctx != nullptr) -+ { -+ gnutls_hash_deinit(ctx, digest_val); -+ ctx = nullptr; -+ } -+ -+ finalized = true; -+} -+ -+// MD5 basic transformation. Transforms state based on block. -+void MD5::transform(UINT4 state[4], unsigned char block[64]) -+{} -+ -+// Encodes input (UINT4) into output (unsigned char). Assumes len is a -+// multiple of 4. -+void MD5::encode(unsigned char *output, UINT4 *input, unsigned int len) -+{} -+ -+// Decodes input (unsigned char) into output (UINT4). Assumes len is a -+// multiple of 4. -+void MD5::decode(UINT4 *output, unsigned char *input, unsigned int len) -+{} -diff --git a/libqpdf/MD5.cc b/libqpdf/MD5.cc -index 0504e2d..19dce79 100644 ---- a/libqpdf/MD5.cc -+++ b/libqpdf/MD5.cc -@@ -36,6 +36,10 @@ - #include - #include - -+#ifdef HAVE_GNUTLS -+# include "MD5-gnutls.cc" -+#else -+ - int const S11 = 7; - int const S12 = 12; - int const S13 = 17; -@@ -294,6 +298,8 @@ void MD5::decode(UINT4 *output, unsigned char *input, unsigned int len) - (static_cast(input[j+3]) << 24); - } - -+#endif /* HAVE_GNUTLS */ -+ - // Public functions - - MD5::MD5() -diff --git a/libqpdf/Pl_AES_PDF-gnutls.cc b/libqpdf/Pl_AES_PDF-gnutls.cc -new file mode 100644 -index 0000000..7704e6d ---- /dev/null -+++ b/libqpdf/Pl_AES_PDF-gnutls.cc -@@ -0,0 +1,246 @@ -+#include -+#include -+#include -+ -+bool Pl_AES_PDF::use_static_iv = false; -+ -+Pl_AES_PDF::Pl_AES_PDF(char const* identifier, Pipeline* next, -+ bool encrypt, unsigned char const* key, -+ unsigned int key_bytes) : -+ Pipeline(identifier, next), -+ encrypt(encrypt), -+ cbc_mode(true), -+ first(true), -+ offset(0), -+ nrounds(0), -+ use_zero_iv(false), -+ use_specified_iv(false), -+ disable_padding(false) -+{ -+ unsigned int keybits = 8 * key_bytes; -+ this->keylen = key_bytes; -+ this->ctx = nullptr; -+ assert(key_bytes == KEYLENGTH(keybits)); -+ this->key = new unsigned char[key_bytes]; -+ this->rk = new uint32_t[RKLENGTH(keybits)]; -+ unsigned int rk_bytes = RKLENGTH(keybits) * sizeof(uint32_t); -+ std::memcpy(this->key, key, key_bytes); -+ std::memset(this->rk, 0, rk_bytes); -+ std::memset(this->inbuf, 0, this->buf_size); -+ std::memset(this->outbuf, 0, this->buf_size); -+ std::memset(this->cbc_block, 0, this->buf_size); -+} -+ -+Pl_AES_PDF::~Pl_AES_PDF() -+{ -+ delete [] this->key; -+ delete [] this->rk; -+} -+ -+void -+Pl_AES_PDF::useZeroIV() -+{ -+ this->use_zero_iv = true; -+} -+ -+void -+Pl_AES_PDF::disablePadding() -+{ -+ this->disable_padding = true; -+} -+ -+void -+Pl_AES_PDF::setIV(unsigned char const* iv, size_t bytes) -+{ -+ if (bytes != this->buf_size) -+ { -+ throw std::logic_error( -+ "Pl_AES_PDF: specified initialization vector" -+ " size in bytes must be " + QUtil::int_to_string(bytes)); -+ } -+ this->use_specified_iv = true; -+ memcpy(this->specified_iv, iv, bytes); -+} -+ -+void -+Pl_AES_PDF::disableCBC() -+{ -+ this->cbc_mode = false; -+} -+ -+void -+Pl_AES_PDF::useStaticIV() -+{ -+ use_static_iv = true; -+} -+ -+void -+Pl_AES_PDF::write(unsigned char* data, size_t len) -+{ -+ size_t bytes_left = len; -+ unsigned char* p = data; -+ -+ while (bytes_left > 0) -+ { -+ if (this->offset == this->buf_size) -+ { -+ flush(false); -+ } -+ -+ size_t available = this->buf_size - this->offset; -+ size_t bytes = (bytes_left < available ? bytes_left : available); -+ bytes_left -= bytes; -+ std::memcpy(this->inbuf + this->offset, p, bytes); -+ this->offset += bytes; -+ p += bytes; -+ } -+} -+ -+void -+Pl_AES_PDF::finish() -+{ -+ if (this->encrypt) -+ { -+ if (this->offset == this->buf_size) -+ { -+ flush(false); -+ } -+ if (! this->disable_padding) -+ { -+ // Pad as described in section 3.5.1 of version 1.7 of the PDF -+ // specification, including providing an entire block of padding -+ // if the input was a multiple of 16 bytes. -+ unsigned char pad = -+ static_cast(this->buf_size - this->offset); -+ memset(this->inbuf + this->offset, pad, pad); -+ this->offset = this->buf_size; -+ flush(false); -+ } -+ } -+ else -+ { -+ if (this->offset != this->buf_size) -+ { -+ // This is never supposed to happen as the output is -+ // always supposed to be padded. However, we have -+ // encountered files for which the output is not a -+ // multiple of the block size. In this case, pad with -+ // zeroes and hope for the best. -+ assert(this->buf_size > this->offset); -+ std::memset(this->inbuf + this->offset, 0, -+ this->buf_size - this->offset); -+ this->offset = this->buf_size; -+ } -+ flush(! this->disable_padding); -+ } -+ -+ if (this->cbc_mode) -+ rijndaelFinish(this->ctx); -+ -+ getNext()->finish(); -+} -+ -+void -+Pl_AES_PDF::initializeVector() -+{ -+ if (use_zero_iv) -+ { -+ for (unsigned int i = 0; i < this->buf_size; ++i) -+ { -+ this->cbc_block[i] = 0; -+ } -+ } -+ else if (use_specified_iv) -+ { -+ std::memcpy(this->cbc_block, this->specified_iv, this->buf_size); -+ } -+ else if (use_static_iv) -+ { -+ for (unsigned int i = 0; i < this->buf_size; ++i) -+ { -+ this->cbc_block[i] = 14 * (1 + i); -+ } -+ } -+ else -+ { -+ QUtil::initializeWithRandomBytes(this->cbc_block, this->buf_size); -+ } -+} -+ -+void -+Pl_AES_PDF::flush(bool strip_padding) -+{ -+ assert(this->offset == this->buf_size); -+ -+ if (first) -+ { -+ first = false; -+ if (this->cbc_mode) -+ { -+ if (encrypt) -+ { -+ // Set cbc_block to the initialization vector, and if -+ // not zero, write it to the output stream. -+ initializeVector(); -+ if (! (this->use_zero_iv || this->use_specified_iv)) -+ { -+ getNext()->write(this->cbc_block, this->buf_size); -+ } -+ } -+ else if (this->use_zero_iv || this->use_specified_iv) -+ { -+ // Initialize vector with zeroes; zero vector was not -+ // written to the beginning of the input file. -+ initializeVector(); -+ } -+ else -+ { -+ // Take the first block of input as the initialization -+ // vector. There's nothing to write at this time. -+ memcpy(this->cbc_block, this->inbuf, this->buf_size); -+ this->offset = 0; -+ rijndaelInit(&(this->ctx), this->key, this->keylen, this->cbc_block, this->buf_size); -+ return; -+ } -+ rijndaelInit(&(this->ctx), this->key, this->keylen, this->cbc_block, this->buf_size); -+ } -+ } -+ -+ if (this->encrypt) -+ { -+ if (this->cbc_mode) -+ rijndaelCBCEncrypt(this->ctx, this->inbuf, this->outbuf, this->buf_size); -+ else -+ rijndaelECBEncrypt(this->key, this->keylen, this->cbc_block, this->inbuf, this->outbuf, this->buf_size); -+ } -+ else -+ { -+ if (this->cbc_mode) -+ rijndaelCBCDecrypt(this->ctx, this->inbuf, this->outbuf, this->buf_size); -+ else -+ rijndaelECBDecrypt(this->key, this->keylen, this->cbc_block, this->inbuf, this->outbuf, this->buf_size); -+ } -+ unsigned int bytes = this->buf_size; -+ if (strip_padding) -+ { -+ unsigned char last = this->outbuf[this->buf_size - 1]; -+ if (last <= this->buf_size) -+ { -+ bool strip = true; -+ for (unsigned int i = 1; i <= last; ++i) -+ { -+ if (this->outbuf[this->buf_size - i] != last) -+ { -+ strip = false; -+ break; -+ } -+ } -+ if (strip) -+ { -+ bytes -= last; -+ } -+ } -+ } -+ getNext()->write(this->outbuf, bytes); -+ this->offset = 0; -+} -diff --git a/libqpdf/Pl_AES_PDF.cc b/libqpdf/Pl_AES_PDF.cc -index 5c493cb..ac8bde4 100644 ---- a/libqpdf/Pl_AES_PDF.cc -+++ b/libqpdf/Pl_AES_PDF.cc -@@ -3,10 +3,15 @@ - #include - #include - #include --#include -+ - #include - #include - -+#ifdef HAVE_GNUTLS -+# include "Pl_AES_PDF-gnutls.cc" -+#else -+# include -+ - bool Pl_AES_PDF::use_static_iv = false; - - Pl_AES_PDF::Pl_AES_PDF(char const* identifier, Pipeline* next, -@@ -263,3 +268,4 @@ Pl_AES_PDF::flush(bool strip_padding) - getNext()->write(this->outbuf, bytes); - this->offset = 0; - } -+#endif -diff --git a/libqpdf/Pl_SHA2.cc b/libqpdf/Pl_SHA2.cc -index 17eff7e..9156451 100644 ---- a/libqpdf/Pl_SHA2.cc -+++ b/libqpdf/Pl_SHA2.cc -@@ -13,6 +13,12 @@ Pl_SHA2::Pl_SHA2(int bits, Pipeline* next) : - { - resetBits(bits); - } -+ -+#ifdef HAVE_GNUTLS -+ this->ctx256 = nullptr; -+ this->ctx384 = nullptr; -+ this->ctx512 = nullptr; -+#endif - } - - Pl_SHA2::~Pl_SHA2() -diff --git a/libqpdf/RC4-gnutls.cc b/libqpdf/RC4-gnutls.cc -new file mode 100644 -index 0000000..093a5b9 ---- /dev/null -+++ b/libqpdf/RC4-gnutls.cc -@@ -0,0 +1,51 @@ -+#include -+#include -+#include -+ -+ -+RC4::RC4(unsigned char const* key_data, int key_len) -+{ -+ if (key_len == -1) -+ { -+ key_len = strlen(reinterpret_cast(key_data)); -+ } -+ -+ int ret; -+ gnutls_cipher_algorithm_t alg = GNUTLS_CIPHER_ARCFOUR_128; -+ -+ this->key.data = const_cast(key_data); -+ this->key.size = key_len; -+ -+ ret = gnutls_cipher_init(&(this->ctx), -+ alg, -+ &(this->key), -+ NULL); -+ if (ret < 0) -+ { -+ QUtil::throw_system_error( -+ std::string("GNU TLS: RC4 error: ") + std::string(gnutls_strerror(ret))); -+ this->ctx = nullptr; -+ } -+} -+ -+RC4::~RC4() -+{ -+ if (this->ctx != nullptr) -+ { -+ gnutls_cipher_deinit(this->ctx); -+ this->ctx = nullptr; -+ } -+} -+ -+void -+RC4::process(unsigned char *in_data, int len, unsigned char* out_data) -+{ -+ if (out_data == 0) -+ { -+ // Convert in place -+ out_data = in_data; -+ } -+ -+ if (this->ctx != nullptr && in_data != nullptr) -+ gnutls_cipher_encrypt2(this->ctx, in_data, len, out_data, len); -+} -diff --git a/libqpdf/RC4.cc b/libqpdf/RC4.cc -index 7639a36..c1288be 100644 ---- a/libqpdf/RC4.cc -+++ b/libqpdf/RC4.cc -@@ -2,6 +2,10 @@ - - #include - -+#ifdef HAVE_GNUTLS -+# include "RC4-gnutls.cc" -+#else -+ - static void swap_byte(unsigned char &a, unsigned char &b) - { - unsigned char t; -@@ -53,3 +57,4 @@ RC4::process(unsigned char *in_data, int len, unsigned char* out_data) - out_data[i] = in_data[i] ^ key.state[xor_index]; - } - } -+#endif -diff --git a/libqpdf/SecureRandomDataProvider.cc b/libqpdf/SecureRandomDataProvider.cc -index fe9f1d4..d72269e 100644 ---- a/libqpdf/SecureRandomDataProvider.cc -+++ b/libqpdf/SecureRandomDataProvider.cc -@@ -11,6 +11,10 @@ - # endif - #endif - -+#ifdef HAVE_GNUTLS -+# include -+#endif -+ - SecureRandomDataProvider::SecureRandomDataProvider() - { - } -@@ -89,7 +93,19 @@ class WindowsCryptProvider - void - SecureRandomDataProvider::provideRandomData(unsigned char* data, size_t len) - { --#if defined(_WIN32) -+#if defined(HAVE_GNUTLS) -+ -+ int ret = 0; -+ -+ ret = gnutls_rnd(GNUTLS_RND_NONCE, data, len); -+ if (ret < 0) -+ { -+ throw std::runtime_error( -+ "GNU TLS: unable to generate secure random data " + -+ std::string(gnutls_strerror(ret))); -+ } -+ -+#elif defined(_WIN32) - - // Optimization: make the WindowsCryptProvider static as long as - // it can be done in a thread-safe fashion. -diff --git a/libqpdf/qpdf/MD5.hh b/libqpdf/qpdf/MD5.hh -index 4cfe027..bb9f756 100644 ---- a/libqpdf/qpdf/MD5.hh -+++ b/libqpdf/qpdf/MD5.hh -@@ -11,6 +11,10 @@ - #endif - #include - -+#ifdef HAVE_GNUTLS -+# include -+#endif -+ - class MD5 - { - public: -@@ -87,6 +91,9 @@ class MD5 - - bool finalized; - Digest digest_val; -+#ifdef HAVE_GNUTLS -+ gnutls_hash_hd_t ctx; -+#endif - }; - - #endif // __MD5_HH__ -diff --git a/libqpdf/qpdf/Pl_AES_PDF.hh b/libqpdf/qpdf/Pl_AES_PDF.hh -index 9aa73ad..8059e7d 100644 ---- a/libqpdf/qpdf/Pl_AES_PDF.hh -+++ b/libqpdf/qpdf/Pl_AES_PDF.hh -@@ -7,6 +7,10 @@ - # include - #endif - -+#ifdef HAVE_GNUTLS -+# include -+#endif -+ - // This pipeline implements AES-128 and AES-256 with CBC and block - // padding as specified in the PDF specification. - -@@ -64,6 +68,11 @@ class Pl_AES_PDF: public Pipeline - bool use_zero_iv; - bool use_specified_iv; - bool disable_padding; -+ -+#ifdef HAVE_GNUTLS -+ gnutls_cipher_hd_t ctx; -+ unsigned int keylen; -+#endif - }; - - #endif // __PL_AES_PDF_HH__ -diff --git a/libqpdf/qpdf/RC4.hh b/libqpdf/qpdf/RC4.hh -index c26f3d0..1421a08 100644 ---- a/libqpdf/qpdf/RC4.hh -+++ b/libqpdf/qpdf/RC4.hh -@@ -1,6 +1,12 @@ - #ifndef __RC4_HH__ - #define __RC4_HH__ - -+#include -+ -+#ifdef HAVE_GNUTLS -+# include -+#endif -+ - class RC4 - { - public: -@@ -10,7 +16,15 @@ class RC4 - // out_data = 0 means to encrypt/decrypt in place - void process(unsigned char* in_data, int len, unsigned char* out_data = 0); - -+#ifdef HAVE_GNUTLS -+ ~RC4(); -+#endif -+ - private: -+#ifdef HAVE_GNUTLS -+ gnutls_cipher_hd_t ctx; -+ gnutls_datum_t key; -+#else - class RC4Key - { - public: -@@ -20,6 +34,7 @@ class RC4 - }; - - RC4Key key; -+#endif - }; - - #endif // __RC4_HH__ -diff --git a/libqpdf/qpdf/rijndael-gnutls.h b/libqpdf/qpdf/rijndael-gnutls.h -new file mode 100644 -index 0000000..a3e7ff0 ---- /dev/null -+++ b/libqpdf/qpdf/rijndael-gnutls.h -@@ -0,0 +1,32 @@ -+#ifdef HAVE_INTTYPES_H -+# include -+#endif -+#ifdef HAVE_STDINT_H -+# include -+#endif -+ -+#include -+ -+void rijndaelInit(gnutls_cipher_hd_t * context, unsigned char * key, -+ unsigned int keylen, unsigned char cbc_block[16], unsigned int buf_size); -+int rijndaelSetupEncrypt(uint32_t *rk, const unsigned char *key, -+ int keybits); -+int rijndaelSetupDecrypt(uint32_t *rk, const unsigned char *key, -+ int keybits); -+void rijndaelCBCEncrypt(gnutls_cipher_hd_t context, -+ const unsigned char plaintext[16], unsigned char ciphertext[16], -+ unsigned int buf_size); -+void rijndaelCBCDecrypt(gnutls_cipher_hd_t context, -+ const unsigned char ciphertext[16], unsigned char plaintext[16], -+ unsigned int buf_size); -+void rijndaelECBEncrypt(unsigned char * key, unsigned int keylen, -+ unsigned char cbc_block[16], const unsigned char plaintext[16], -+ unsigned char ciphertext[16], unsigned int buf_size); -+void rijndaelECBDecrypt(unsigned char * key, unsigned int keylen, -+ unsigned char cbc_block[16], const unsigned char ciphertext[16], -+ unsigned char plaintext[16], unsigned int buf_size); -+void rijndaelFinish(gnutls_cipher_hd_t context); -+ -+#define KEYLENGTH(keybits) ((keybits)/8) -+#define RKLENGTH(keybits) ((keybits)/8+28) -+#define NROUNDS(keybits) ((keybits)/32+6) -diff --git a/libqpdf/qpdf/rijndael.h b/libqpdf/qpdf/rijndael.h -index a9cd71d..9698a8b 100644 ---- a/libqpdf/qpdf/rijndael.h -+++ b/libqpdf/qpdf/rijndael.h -@@ -9,6 +9,10 @@ - # include - #endif - -+#ifdef HAVE_GNUTLS -+# include "qpdf/rijndael-gnutls.h" -+#else -+ - int rijndaelSetupEncrypt(uint32_t *rk, const unsigned char *key, - int keybits); - int rijndaelSetupDecrypt(uint32_t *rk, const unsigned char *key, -@@ -22,4 +26,6 @@ void rijndaelDecrypt(const uint32_t *rk, int nrounds, - #define RKLENGTH(keybits) ((keybits)/8+28) - #define NROUNDS(keybits) ((keybits)/32+6) - -+#endif /* HAVE_GNUTLS */ -+ - #endif -diff --git a/libqpdf/rijndael-gnutls.cc b/libqpdf/rijndael-gnutls.cc -new file mode 100644 -index 0000000..dd3fdb2 ---- /dev/null -+++ b/libqpdf/rijndael-gnutls.cc -@@ -0,0 +1,116 @@ -+#include -+#include -+#include -+#include -+ -+typedef uint32_t u32; -+ -+/** -+ * Init cryptographic context -+ */ -+void rijndaelInit(gnutls_cipher_hd_t * ctx, unsigned char * key, -+ unsigned int keylen, unsigned char cbc_block[16], -+ unsigned int buf_size) -+{ -+ int ret; -+ gnutls_cipher_algorithm_t alg; -+ gnutls_datum_t cipher_key; -+ gnutls_datum_t iv; -+ -+ cipher_key.data = key; -+ -+ switch(keylen) { -+ case 16: -+ alg = GNUTLS_CIPHER_AES_128_CBC; -+ break; -+ case 32: -+ alg = GNUTLS_CIPHER_AES_256_CBC; -+ break; -+ case 24: -+ alg = GNUTLS_CIPHER_AES_192_CBC; -+ break; -+ default: -+ alg = GNUTLS_CIPHER_AES_128_CBC; -+ break; -+ } -+ -+ cipher_key.size = gnutls_cipher_get_key_size(alg); -+ -+ iv.data = cbc_block; -+ iv.size = buf_size; -+ -+ ret = gnutls_cipher_init(ctx, alg, &cipher_key, &iv); -+ if (ret < 0) -+ { -+ QUtil::throw_system_error( -+ std::string("GNU TLS: AES error: ") + std::string(gnutls_strerror(ret))); -+ ctx = NULL; -+ return; -+ } -+} -+ -+/** -+ * Encrypt string by AES CBC by GNU TLS. -+ */ -+void rijndaelCBCEncrypt(gnutls_cipher_hd_t ctx, -+ const unsigned char plaintext[16], unsigned char ciphertext[16], -+ unsigned int buf_size) -+{ -+ if (ctx != nullptr) -+ gnutls_cipher_encrypt2(ctx, plaintext, buf_size, ciphertext, buf_size); -+} -+ -+/** -+ * Decrypt string by AES CBC by GNU TLS. -+ */ -+void rijndaelCBCDecrypt(gnutls_cipher_hd_t ctx, -+ const unsigned char ciphertext[16], unsigned char plaintext[16], -+ unsigned int buf_size) -+{ -+ if (ctx != nullptr) -+ gnutls_cipher_decrypt2(ctx, ciphertext, buf_size, plaintext, buf_size); -+} -+ -+/** -+ * Encrypt string by AES ECB by GNU TLS. -+ */ -+void rijndaelECBEncrypt(unsigned char * key, unsigned int keylen, -+ unsigned char cbc_block[16], const unsigned char ciphertext[16], -+ unsigned char plaintext[16], unsigned int buf_size) -+{ -+ gnutls_cipher_hd_t ctx; -+ -+ rijndaelInit(&ctx, key, keylen, cbc_block, buf_size); -+ -+ rijndaelCBCEncrypt(ctx, ciphertext, plaintext, buf_size); -+ -+ rijndaelFinish(ctx); -+} -+ -+/** -+ * Decrypt string by AES ECB by GNU TLS. -+ */ -+void rijndaelECBDecrypt(unsigned char * key, unsigned int keylen, -+ unsigned char cbc_block[16], const unsigned char ciphertext[16], -+ unsigned char plaintext[16], unsigned int buf_size) -+{ -+ gnutls_cipher_hd_t ctx; -+ -+ rijndaelInit(&ctx, key, keylen, cbc_block, buf_size); -+ -+ rijndaelCBCDecrypt(ctx, ciphertext, plaintext, buf_size); -+ -+ rijndaelFinish(ctx); -+} -+ -+/** -+ * Finish cryptography context -+ */ -+void rijndaelFinish(gnutls_cipher_hd_t ctx) -+{ -+ if (ctx != nullptr) -+ { -+ gnutls_cipher_deinit(ctx); -+ ctx = nullptr; -+ } -+} -diff --git a/libqpdf/rijndael.cc b/libqpdf/rijndael.cc -index 7f711df..117c1a1 100644 ---- a/libqpdf/rijndael.cc -+++ b/libqpdf/rijndael.cc -@@ -2,6 +2,10 @@ - - #include "qpdf/rijndael.h" - -+#ifdef HAVE_GNUTLS -+# include "rijndael-gnutls.cc" -+#else -+ - typedef uint32_t u32; - typedef unsigned char u8; - -@@ -1206,3 +1210,4 @@ void rijndaelDecrypt(const u32 *rk, int nrounds, const u8 ciphertext[16], - rk[3]; - PUTU32(plaintext + 12, s3); - } -+#endif -diff --git a/libqpdf/sha2-gnutls.c b/libqpdf/sha2-gnutls.c -new file mode 100644 -index 0000000..29155d5 ---- /dev/null -+++ b/libqpdf/sha2-gnutls.c -@@ -0,0 +1,41 @@ -+#include -+#include -+#include "sph/sph_sha2_gnutls.h" -+ -+ -+/* see sph_sha2.h */ -+void -+sph_sha256_init(void * cc) -+{ -+ int ret; -+ gnutls_hash_hd_t * ctx = (gnutls_hash_hd_t*) cc; -+ -+ ret = gnutls_hash_init(ctx, GNUTLS_DIG_SHA256); -+ if (ret < 0) -+ { -+ fprintf(stderr, "GNU TLS: SHA256 error : %s\n", gnutls_strerror(ret)); -+ cc = NULL; -+ } -+} -+ -+/* see sph_sha2.h */ -+void -+sph_sha256_close(void * cc, void *dst) -+{ -+ gnutls_hash_hd_t * ctx = (gnutls_hash_hd_t*) cc; -+ -+ if (ctx != NULL) -+ { -+ gnutls_hash_deinit(*(ctx), dst); -+ cc = NULL; -+ } -+} -+ -+/* see sph_sha2.h */ -+void sph_sha256(void * cc, const void * data, size_t len) -+{ -+ gnutls_hash_hd_t * ctx = (gnutls_hash_hd_t*) cc; -+ -+ if (ctx != NULL && data != NULL) -+ gnutls_hash(*(ctx), data, len); -+} -diff --git a/libqpdf/sha2.c b/libqpdf/sha2.c -index 45fdd7e..e240f9b 100644 ---- a/libqpdf/sha2.c -+++ b/libqpdf/sha2.c -@@ -35,6 +35,10 @@ - - #include "sph/sph_sha2.h" - -+#ifdef HAVE_GNUTLS -+# include "sha2-gnutls.c" -+#else -+ - #if SPH_SMALL_FOOTPRINT && !defined SPH_SMALL_FOOTPRINT_SHA2 - #define SPH_SMALL_FOOTPRINT_SHA2 1 - #endif -@@ -688,3 +692,5 @@ sph_sha224_comp(const sph_u32 msg[16], sph_u32 val[8]) - SHA2_ROUND_BODY(SHA2_IN, val); - #undef SHA2_IN - } -+ -+#endif /* HAVE_GNUTLS */ -diff --git a/libqpdf/sha2big-gnutls.c b/libqpdf/sha2big-gnutls.c -new file mode 100644 -index 0000000..494e2b4 ---- /dev/null -+++ b/libqpdf/sha2big-gnutls.c -@@ -0,0 +1,80 @@ -+#include -+#include -+#include "sph/sph_sha2_gnutls.h" -+ -+ -+/* see sph_sha3.h */ -+void -+sph_sha384_init(void * cc) -+{ -+ int ret; -+ gnutls_hash_hd_t * ctx = (gnutls_hash_hd_t*) cc; -+ -+ ret = gnutls_hash_init(ctx, GNUTLS_DIG_SHA384); -+ if (ret < 0) -+ { -+ fprintf(stderr, "GNU TLS: SHA384 error: %s\n", gnutls_strerror(ret)); -+ cc = NULL; -+ } -+} -+ -+/* see sph_sha3.h */ -+void -+sph_sha384_close(void * cc, void *dst) -+{ -+ gnutls_hash_hd_t * ctx = (gnutls_hash_hd_t*) cc; -+ -+ if (ctx != NULL && dst != NULL) -+ { -+ gnutls_hash_deinit(*(ctx), dst); -+ cc = NULL; -+ } -+} -+ -+/* see sph_sha3.h */ -+void -+sph_sha384(void * cc, const void * data, size_t len) -+{ -+ gnutls_hash_hd_t * ctx = (gnutls_hash_hd_t*) cc; -+ -+ if (ctx != NULL && data != NULL) -+ gnutls_hash(*(ctx), data, len); -+} -+ -+/* see sph_sha3.h */ -+void -+sph_sha512_init(void * cc) -+{ -+ int ret; -+ gnutls_hash_hd_t * ctx = (gnutls_hash_hd_t*) cc; -+ -+ ret = gnutls_hash_init(ctx, GNUTLS_DIG_SHA512); -+ if (ret < 0) -+ { -+ fprintf(stderr, "GNU TLS: SHA512 error: %s\n", gnutls_strerror(ret)); -+ cc = NULL; -+ } -+} -+ -+/* see sph_sha3.h */ -+void -+sph_sha512_close(void * cc, void * dst) -+{ -+ gnutls_hash_hd_t * ctx = (gnutls_hash_hd_t*) cc; -+ -+ if (ctx != NULL && dst != NULL) -+ { -+ gnutls_hash_deinit(*(ctx), dst); -+ cc = NULL; -+ } -+} -+ -+/* see sph_sha3.h */ -+void -+sph_sha512(void * cc, const void * data, size_t len) -+{ -+ gnutls_hash_hd_t * ctx = (gnutls_hash_hd_t*) cc; -+ -+ if (ctx != NULL && data != NULL) -+ gnutls_hash(*(ctx), data, len); -+} -diff --git a/libqpdf/sha2big.c b/libqpdf/sha2big.c -index e4aadbd..3194a10 100644 ---- a/libqpdf/sha2big.c -+++ b/libqpdf/sha2big.c -@@ -35,6 +35,10 @@ - - #include "sph/sph_sha2.h" - -+#ifdef HAVE_GNUTLS -+# include "sha2big-gnutls.c" -+#else -+ - #if SPH_64 - - #define CH(X, Y, Z) ((((Y) ^ (Z)) & (X)) ^ (Z)) -@@ -245,3 +249,5 @@ sph_sha384_comp(const sph_u64 msg[16], sph_u64 val[8]) - } - - #endif -+ -+#endif /* HAVE_GNUTLS */ -diff --git a/libqpdf/sph/sph_sha2.h b/libqpdf/sph/sph_sha2.h -index 4bff9cd..584c6ab 100644 ---- a/libqpdf/sph/sph_sha2.h -+++ b/libqpdf/sph/sph_sha2.h -@@ -47,6 +47,12 @@ extern "C" { - #include - #include "sph_types.h" - -+#include -+ -+#ifdef HAVE_GNUTLS -+# include "sph_sha2_gnutls.h" -+#else -+ - /** - * Output size (in bits) for SHA-224. - */ -@@ -371,6 +377,8 @@ void sph_sha512_comp(const sph_u64 msg[16], sph_u64 val[8]); - - #endif - -+#endif /* HAVE_GNUTLS */ -+ - #ifdef __cplusplus - } - #endif -diff --git a/libqpdf/sph/sph_sha2_gnutls.h b/libqpdf/sph/sph_sha2_gnutls.h -new file mode 100644 -index 0000000..1fb26a4 ---- /dev/null -+++ b/libqpdf/sph/sph_sha2_gnutls.h -@@ -0,0 +1,88 @@ -+#include -+#include -+ -+typedef gnutls_hash_hd_t sph_sha256_context; -+typedef gnutls_hash_hd_t sph_sha384_context; -+typedef gnutls_hash_hd_t sph_sha512_context; -+ -+/** -+ * Initialize a SHA-256 context. -+ * -+ * @param cc the SHA-256 context (pointer to -+ * a sph_sha256_context) -+ */ -+void sph_sha256_init(void *cc); -+ -+/** -+ * Process some data bytes, for SHA-256. -+ * -+ * @param cc the SHA-224 context -+ * @param data the input data -+ * @param len the input data length (in bytes) -+ */ -+void sph_sha256(void *cc, const void *data, size_t len); -+ -+/** -+ * Terminate the current SHA-256 computation and output the result into the -+ * provided buffer. The destination buffer must be wide enough to -+ * accomodate the result (32 bytes). -+ * -+ * @param cc the SHA-256 context -+ * @param dst the destination buffer -+ */ -+void sph_sha256_close(void *cc, void *dst); -+ -+/** -+ * Initialize a SHA-384 context. -+ * -+ * @param cc the SHA-384 context (pointer to -+ * a sph_sha384_context) -+ */ -+void sph_sha384_init(void *cc); -+ -+/** -+ * Process some data bytes. It is acceptable that len is zero -+ * (in which case this function does nothing). -+ * -+ * @param cc the SHA-384 context -+ * @param data the input data -+ * @param len the input data length (in bytes) -+ */ -+void sph_sha384(void *cc, const void *data, size_t len); -+ -+/** -+ * Terminate the current SHA-384 computation and output the result into the -+ * provided buffer. The destination buffer must be wide enough to -+ * accomodate the result (48 bytes). -+ * -+ * @param cc the SHA-384 context -+ * @param dst the destination buffer -+ */ -+void sph_sha384_close(void *cc, void *dst); -+ -+/** -+ * Initialize a SHA-512 context. -+ * -+ * @param cc the SHA-512 context (pointer to -+ * a sph_sha512_context) -+ */ -+void sph_sha512_init(void *cc); -+ -+/** -+ * Process some data bytes, for SHA-512. -+ * -+ * @param cc the SHA-384 context -+ * @param data the input data -+ * @param len the input data length (in bytes) -+ */ -+void sph_sha512(void *cc, const void *data, size_t len); -+ -+/** -+ * Terminate the current SHA-512 computation and output the result into the -+ * provided buffer. The destination buffer must be wide enough to -+ * accomodate the result (64 bytes). -+ * -+ * @param cc the SHA-512 context -+ * @param dst the destination buffer -+ */ -+void sph_sha512_close(void *cc, void *dst); -diff --git a/libqpdf/sph/sph_types.h b/libqpdf/sph/sph_types.h -index eab09a2..36d1ff6 100644 ---- a/libqpdf/sph/sph_types.h -+++ b/libqpdf/sph/sph_types.h -@@ -48,6 +48,7 @@ - #define SPH_TYPES_H__ - - #include -+#include - - /* - * All our I/O functions are defined over octet streams. We do not know diff --git a/qpdf-relax.patch b/qpdf-relax.patch index 3f7c8d9..9861daf 100644 --- a/qpdf-relax.patch +++ b/qpdf-relax.patch @@ -1,158 +1,198 @@ -diff --git a/libqpdf/QPDF.cc b/libqpdf/QPDF.cc -index 3475afe..f93ba0d 100644 ---- a/libqpdf/QPDF.cc -+++ b/libqpdf/QPDF.cc -@@ -19,6 +19,10 @@ - #include - #include +diff -up qpdf-11.7.0/libqpdf/QPDF.cc.relax qpdf-11.7.0/libqpdf/QPDF.cc +--- qpdf-11.7.0/libqpdf/QPDF.cc.relax 2023-12-24 13:36:07.000000000 +0100 ++++ qpdf-11.7.0/libqpdf/QPDF.cc 2024-01-08 15:17:27.020951639 +0100 +@@ -13,6 +13,10 @@ + #include + #include -+#ifdef HAVE_GNUTLS ++#ifdef USE_CRYPTO_GNUTLS +# include +#endif + - std::string QPDF::qpdf_version = "7.1.1"; - - static char const* EMPTY_PDF = -@@ -139,7 +143,13 @@ QPDF::processFile(char const* filename, char const* password) + #include + #include + #include +@@ -250,14 +254,26 @@ void + QPDF::processFile(char const* filename, char const* password) { - FileInputSource* fi = new FileInputSource(); - fi->setFilename(filename); -+#ifdef HAVE_GNUTLS + auto* fi = new FileInputSource(filename); ++#ifdef USE_CRYPTO_GNUTLS + GNUTLS_FIPS140_SET_LAX_MODE(); +#endif - processInputSource(fi, password); -+#ifdef HAVE_GNUTLS + processInputSource(std::shared_ptr(fi), password); ++#ifdef USE_CRYPTO_GNUTLS + GNUTLS_FIPS140_SET_STRICT_MODE(); +#endif } void -@@ -148,7 +158,13 @@ QPDF::processFile(char const* description, FILE* filep, + QPDF::processFile(char const* description, FILE* filep, bool close_file, char const* password) { - FileInputSource* fi = new FileInputSource(); - fi->setFile(description, filep, close_file); -+#ifdef HAVE_GNUTLS + auto* fi = new FileInputSource(description, filep, close_file); ++#ifdef USE_CRYPTO_GNUTLS + GNUTLS_FIPS140_SET_LAX_MODE(); +#endif - processInputSource(fi, password); -+#ifdef HAVE_GNUTLS + processInputSource(std::shared_ptr(fi), password); ++#ifdef USE_CRYPTO_GNUTLS + GNUTLS_FIPS140_SET_STRICT_MODE(); +#endif } void -diff --git a/libqpdf/QPDFWriter.cc b/libqpdf/QPDFWriter.cc -index 0544640..48fe50d 100644 ---- a/libqpdf/QPDFWriter.cc -+++ b/libqpdf/QPDFWriter.cc -@@ -23,6 +23,10 @@ - #include - #include +diff -up qpdf-11.7.0/libqpdf/QPDF_encryption.cc.relax qpdf-11.7.0/libqpdf/QPDF_encryption.cc +--- qpdf-11.7.0/libqpdf/QPDF_encryption.cc.relax 2023-12-24 13:36:07.000000000 +0100 ++++ qpdf-11.7.0/libqpdf/QPDF_encryption.cc 2024-01-08 15:19:52.303117277 +0100 +@@ -3,6 +3,8 @@ -+#ifdef HAVE_GNUTLS -+#include -+#endif -+ - QPDFWriter::Members::Members(QPDF& pdf) : - pdf(pdf), - filename(0), -@@ -323,6 +327,13 @@ void - QPDFWriter::setDeterministicID(bool val) - { - this->m->deterministic_id = val; -+ -+#ifdef HAVE_GNUTLS -+ if (val) -+ GNUTLS_FIPS140_SET_LAX_MODE(); -+ else -+ GNUTLS_FIPS140_SET_STRICT_MODE(); -+#endif - } - - void -@@ -344,6 +355,13 @@ void - QPDFWriter::setPreserveEncryption(bool val) - { - this->m->preserve_encryption = val; -+ -+#ifdef HAVE_GNUTLS -+ if (val) -+ GNUTLS_FIPS140_SET_STRICT_MODE(); -+ else -+ GNUTLS_FIPS140_SET_LAX_MODE(); -+#endif - } - - void -diff --git a/libqpdf/QPDF_encryption.cc b/libqpdf/QPDF_encryption.cc -index fd717c3..9b38914 100644 ---- a/libqpdf/QPDF_encryption.cc -+++ b/libqpdf/QPDF_encryption.cc -@@ -1,6 +1,8 @@ - // This file implements methods from the QPDF class that involve - // encryption. + #include +#include + #include #include -@@ -18,6 +20,10 @@ - #include - #include +@@ -19,6 +21,10 @@ + #include + #include -+#ifdef HAVE_GNUTLS ++#ifdef USE_CRYPTO_GNUTLS +# include +#endif + static unsigned char const padding_string[] = { - 0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41, - 0x64, 0x00, 0x4e, 0x56, 0xff, 0xfa, 0x01, 0x08, -@@ -1084,6 +1090,12 @@ QPDF::getKeyForObject(int objid, int generation, bool use_aes) - void - QPDF::decryptString(std::string& str, int objid, int generation) - { -+#ifdef HAVE_GNUTLS + 0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41, 0x64, 0x00, 0x4e, 0x56, 0xff, 0xfa, 0x01, 0x08, + 0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80, 0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a}; +@@ -349,10 +355,21 @@ QPDF::compute_data_key( + result += "sAlT"; + } + ++#ifdef USE_CRYPTO_GNUTLS + unsigned oldmode = gnutls_fips140_mode_enabled(); + + gnutls_fips140_set_mode(GNUTLS_FIPS140_LAX, GNUTLS_FIPS140_SET_MODE_THREAD); +#endif + - if (objid == 0) - { - return; -@@ -1162,6 +1174,10 @@ QPDF::decryptString(std::string& str, int objid, int generation) - QUtil::int_to_string(objid) + " " + - QUtil::int_to_string(generation) + ": " + e.what()); + MD5 md5; + md5.encodeDataIncrementally(result.c_str(), result.length()); + MD5::Digest digest; + md5.digest(digest); ++ ++#ifdef USE_CRYPTO_GNUTLS ++ gnutls_fips140_set_mode(static_cast(oldmode), GNUTLS_FIPS140_SET_MODE_THREAD); ++#endif ++ + return {reinterpret_cast(digest), std::min(result.length(), toS(16))}; + } + +@@ -976,6 +993,12 @@ QPDF::getKeyForObject( + void + QPDF::decryptString(std::string& str, QPDFObjGen const& og) + { ++#ifdef USE_CRYPTO_GNUTLS ++ unsigned oldmode = gnutls_fips140_mode_enabled(); ++ ++ gnutls_fips140_set_mode(GNUTLS_FIPS140_LAX, GNUTLS_FIPS140_SET_MODE_THREAD); ++#endif ++ + if (!og.isIndirect()) { + return; + } +@@ -1036,6 +1059,10 @@ QPDF::decryptString(std::string& str, QP + } catch (std::runtime_error& e) { + throw damagedPDF("error decrypting string for object " + og.unparse() + ": " + e.what()); } + -+#ifdef HAVE_GNUTLS ++#ifdef USE_CRYPTO_GNUTLS + gnutls_fips140_set_mode(static_cast(oldmode), GNUTLS_FIPS140_SET_MODE_THREAD); +#endif } - void -@@ -1169,6 +1185,12 @@ QPDF::decryptStream(Pipeline*& pipeline, int objid, int generation, - QPDFObjectHandle& stream_dict, - std::vector >& heap) + // Prepend a decryption pipeline to 'pipeline'. The decryption pipeline (returned as +@@ -1051,6 +1078,12 @@ QPDF::decryptStream( + QPDFObjectHandle& stream_dict, + std::unique_ptr& decrypt_pipeline) { -+#ifdef HAVE_GNUTLS ++#ifdef USE_CRYPTO_GNUTLS + unsigned oldmode = gnutls_fips140_mode_enabled(); + + gnutls_fips140_set_mode(GNUTLS_FIPS140_LAX, GNUTLS_FIPS140_SET_MODE_THREAD); +#endif + std::string type; - if (stream_dict.getKey("/Type").isName()) - { -@@ -1297,6 +1319,10 @@ QPDF::decryptStream(Pipeline*& pipeline, int objid, int generation, - key.length()); + if (stream_dict.getKey("/Type").isName()) { + type = stream_dict.getKey("/Type").getName(); +@@ -1151,6 +1184,10 @@ QPDF::decryptStream( + toI(key.length())); } - heap.push_back(pipeline); + pipeline = decrypt_pipeline.get(); + -+#ifdef HAVE_GNUTLS ++#ifdef USE_CRYPTO_GNUTLS + gnutls_fips140_set_mode(static_cast(oldmode), GNUTLS_FIPS140_SET_MODE_THREAD); +#endif } void +diff -up qpdf-11.7.0/libqpdf/QPDFWriter.cc.relax qpdf-11.7.0/libqpdf/QPDFWriter.cc +--- qpdf-11.7.0/libqpdf/QPDFWriter.cc.relax 2023-12-24 13:36:07.000000000 +0100 ++++ qpdf-11.7.0/libqpdf/QPDFWriter.cc 2024-01-08 15:17:27.022951614 +0100 +@@ -26,6 +26,10 @@ + #include + #include + ++#ifdef USE_CRYPTO_GNUTLS ++#include ++#endif ++ + QPDFWriter::ProgressReporter::~ProgressReporter() // NOLINT (modernize-use-equals-default) + { + // Must be explicit and not inline -- see QPDF_DLL_CLASS in README-maintainer +@@ -287,6 +291,13 @@ void + QPDFWriter::setDeterministicID(bool val) + { + m->deterministic_id = val; ++ ++#ifdef USE_CRYPTO_GNUTLS ++ if (val) ++ GNUTLS_FIPS140_SET_LAX_MODE(); ++ else ++ GNUTLS_FIPS140_SET_STRICT_MODE(); ++#endif + } + + void +@@ -307,6 +318,13 @@ void + QPDFWriter::setPreserveEncryption(bool val) + { + m->preserve_encryption = val; ++ ++#ifdef USE_CRYPTO_GNUTLS ++ if (val) ++ GNUTLS_FIPS140_SET_STRICT_MODE(); ++ else ++ GNUTLS_FIPS140_SET_LAX_MODE(); ++#endif + } + + void +@@ -1890,11 +1908,21 @@ QPDFWriter::generateID() + } + } + ++#ifdef USE_CRYPTO_GNUTLS ++ unsigned oldmode = gnutls_fips140_mode_enabled(); ++ ++ gnutls_fips140_set_mode(GNUTLS_FIPS140_LAX, GNUTLS_FIPS140_SET_MODE_THREAD); ++#endif ++ + MD5 m; + m.encodeString(seed.c_str()); + MD5::Digest digest; + m.digest(digest); + result = std::string(reinterpret_cast(digest), sizeof(MD5::Digest)); ++ ++#ifdef USE_CRYPTO_GNUTLS ++ gnutls_fips140_set_mode(static_cast(oldmode), GNUTLS_FIPS140_SET_MODE_THREAD); ++#endif + } + + // If /ID already exists, follow the spec: use the original first word and generate a new second diff --git a/qpdf.spec b/qpdf.spec index ea6020d..85ed64f 100644 --- a/qpdf.spec +++ b/qpdf.spec @@ -1,56 +1,70 @@ Summary: Command-line tools and library for transforming PDF files Name: qpdf -Version: 7.1.1 -Release: 10%{?dist} -# MIT: e.g. libqpdf/sha2.c -# upstream uses ASL 2.0 now, but he allowed others to distribute qpdf under +Version: 11.8.0 +Release: 5%{?dist} +# MIT: e.g. libqpdf/sha2.c, but those are not compiled in (GNUTLS is used) +# upstream uses ASL 2.0 now, but he allowed other to distribute qpdf under # old license (see README) -License: (Artistic 2.0 or ASL 2.0) and MIT -URL: http://qpdf.sourceforge.net/ -Source0: http://downloads.sourceforge.net/sourceforge/qpdf/qpdf-%{version}.tar.gz +License: Apache-2.0 OR Artistic-2.0 +URL: https://qpdf.sourceforge.io/ +Source0: https://github.com/%{name}/%{name}/releases/download/v%{version}/%{name}-%{version}.tar.gz +Source1: https://github.com/%{name}/%{name}/releases/download/v%{version}/%{name}-%{version}-doc.zip + +# make qpdf working under FIPS, downstream patch +Patch1: qpdf-relax.patch -Patch0: qpdf-doc.patch -Patch1: qpdf-CVE-2018-9918.patch -Patch2: qpdf-gnutls-crypto.patch -Patch3: qpdf-relax.patch # gcc and gcc-c++ are no longer in buildroot by default # gcc is needed for qpdf-ctest.c BuildRequires: gcc # gcc-c++ is need for everything except for qpdf-ctest BuildRequires: gcc-c++ +# uses cmake +BuildRequires: cmake BuildRequires: zlib-devel BuildRequires: libjpeg-turbo-devel -BuildRequires: pcre-devel + +# for gnutls crypto +BuildRequires: gnutls-devel # for fix-qdf and test suite -BuildRequires: perl-interpreter BuildRequires: perl-generators +BuildRequires: perl-interpreter +BuildRequires: perl(Carp) +BuildRequires: perl(Config) +BuildRequires: perl(constant) +BuildRequires: perl(Cwd) BuildRequires: perl(Digest::MD5) +BuildRequires: perl(Digest::SHA) +BuildRequires: perl(File::Basename) +BuildRequires: perl(File::Compare) +BuildRequires: perl(File::Copy) +BuildRequires: perl(File::Find) +BuildRequires: perl(File::Spec) +BuildRequires: perl(FileHandle) +BuildRequires: perl(IO::Handle) +BuildRequires: perl(IO::Select) +BuildRequires: perl(IO::Socket) +BuildRequires: perl(POSIX) +BuildRequires: perl(strict) +# perl(Term::ANSIColor) - not needed for tests +# perl(Term::ReadKey) - not needed for tests -# for autoreconf -BuildRequires: autoconf -BuildRequires: automake -BuildRequires: libtool - -# for crypto by gnutls -BuildRequires: gnutls-devel -BuildRequires: pkgconf-pkg-config - -Requires: qpdf-libs%{?_isa} = %{version}-%{release} +Requires: %{name}-libs%{?_isa} = %{version}-%{release} %package libs Summary: QPDF library for transforming PDF files %package devel Summary: Development files for QPDF library -Requires: qpdf-libs%{?_isa} = %{version}-%{release} +Requires: %{name}-libs%{?_isa} = %{version}-%{release} %package doc Summary: QPDF Manual BuildArch: noarch -Requires: qpdf-libs = %{version}-%{release} +BuildRequires: unzip +Requires: %{name}-libs = %{version}-%{release} %description QPDF is a command-line program that does structural, content-preserving @@ -74,54 +88,57 @@ QPDF Manual %prep %setup -q -# fix 'complete manual location' note in man pages -%patch0 -p1 -b .doc -# CVE-2018-9918 qpdf: stack exhaustion in QPDFObjectHandle and QPDF_Dictionary classes in libqpdf.a [fedora-all] -%patch1 -p1 -b .CVE-2018-9918 -# 1605101 - qpdf: should not re-implement crypto -%patch2 -p1 -b .gnutls-crypto -# 1605101 - downstream patch for relaxing crypto for deterministic id and decrypt -%patch3 -p1 -b .relax +%patch -P 1 -p1 -b .relax + +# unpack zip file with manual +unzip %{SOURCE1} -sed -i -e '1s,^#!/usr/bin/env perl,#!/usr/bin/perl,' qpdf/fix-qdf %build -# work-around check-rpaths errors -autoreconf --verbose --force --install +%cmake -DBUILD_STATIC_LIBS=0 \ + -DREQUIRE_CRYPTO_GNUTLS=1 \ + -DUSE_IMPLICIT_CRYPTO=0 \ + -DSHOW_FAILED_TEST_OUTPUT=1 \ + -DINSTALL_CMAKE_PACKAGE=0 -%configure --disable-static \ - --enable-show-failed-test-output \ - --enable-gnutls - -make %{?_smp_mflags} +%cmake_build %install -make install DESTDIR=%{buildroot} +%cmake_install -rm -f %{buildroot}%{_libdir}/libqpdf.la +install -m 0644 %{name}-%{version}-doc/%{name}-manual.pdf %{buildroot}/%{_pkgdocdir}/%{name}-manual.pdf + +# install bash/zsh completions +mkdir -p %{buildroot}%{bash_completions_dir} +mkdir -p %{buildroot}%{zsh_completions_dir} +install -m 0644 completions/bash/qpdf %{buildroot}%{bash_completions_dir}/qpdf +install -m 0644 completions/zsh/_qpdf %{buildroot}%{zsh_completions_dir}/_qpdf %check -make check +%ctest -%post libs -p /sbin/ldconfig - -%postun libs -p /sbin/ldconfig +%ldconfig_scriptlets libs %files %{_bindir}/fix-qdf %{_bindir}/qpdf %{_bindir}/zlib-flate %{_mandir}/man1/* +%dir %{bash_completions_dir} +%{bash_completions_dir}/qpdf +%dir %{zsh_completions_dir} +%{zsh_completions_dir}/_qpdf %files libs -%doc README.md TODO ChangeLog -%license Artistic-2.0 -%{_libdir}/libqpdf*.so.* +%doc README.md TODO.md ChangeLog +%license Artistic-2.0 LICENSE.txt NOTICE.md +%{_libdir}/libqpdf.so.29 +%{_libdir}/libqpdf.so.29.8.0 %files devel %doc examples/*.cc examples/*.c -%{_includedir}/* -%{_libdir}/libqpdf*.so +%{_includedir}/qpdf/ +%{_libdir}/libqpdf.so %{_libdir}/pkgconfig/libqpdf.pc %files doc @@ -129,24 +146,205 @@ make check %changelog -* Tue Sep 10 2019 Zdenek Dohnal - 7.1.1-10 -- used bad define in previous commit +* Tue Oct 29 2024 Troy Dawson - 11.8.0-5 +- Bump release for October 2024 mass rebuild: + Resolves: RHEL-64018 -* Tue Sep 10 2019 Zdenek Dohnal - 7.1.1-9 -- 1605101 - qpdf: should not re-implement crypto - episode II - relaxing crypto for decrypt +* Mon Jun 24 2024 Troy Dawson - 11.8.0-4 +- Bump release for June 2024 mass rebuild -* Thu Sep 05 2019 Zdenek Dohnal - 7.1.1-8 -- 1605101 - qpdf: should not re-implement crypto +* Fri Jan 26 2024 Fedora Release Engineering - 11.8.0-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild -* Tue Jul 24 2018 Zdenek Dohnal - 7.1.1-7 +* Mon Jan 22 2024 Fedora Release Engineering - 11.8.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild + +* Tue Jan 09 2024 Zdenek Dohnal - 11.8.0-1 +- 2257313 - qpdf-11.8.0 is available + +* Mon Jan 08 2024 Zdenek Dohnal - 11.7.0-1 +- 2255755 - qpdf-11.7.0 is available + +* Tue Dec 19 2023 Zdenek Dohnal - 11.6.4-2 +- 2254778 - remove the tests which fail with zlib-ng-compat for now + +* Mon Dec 18 2023 Zdenek Dohnal - 11.6.4-1 +- 2253901 - qpdf-11.6.4 is available + +* Thu Nov 02 2023 Zdenek Dohnal - 11.6.3-1 +- 2244319 - qpdf-11.6.3 is available + +* Mon Oct 09 2023 Zdenek Dohnal - 11.6.2-1 +- 2242670 - qpdf-11.6.2 is available + +* Tue Sep 12 2023 Zdenek Dohnal - 11.6.1-1 +- 2237125 - qpdf-11.6.1 is available + +* Wed Jul 26 2023 Zdenek Dohnal - 11.5.0-1 +- 2221506 - qpdf-11.5.0 is available + +* Fri Jul 21 2023 Fedora Release Engineering - 11.4.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild + +* Mon May 22 2023 Zdenek Dohnal - 11.4.0-1 +- 2208892 - qpdf-11.4.0 is available + +* Mon Mar 27 2023 Zdenek Dohnal - 11.3.0-2 +- 2181519 - qpdf bash and zsh completion files are missing + +* Thu Mar 02 2023 Zdenek Dohnal - 11.3.0-1 +- 2173354 - qpdf-11.3.0 is available + +* Fri Jan 20 2023 Fedora Release Engineering - 11.2.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild + +* Tue Nov 22 2022 Zdenek Dohnal - 11.2.0-1 +- 2144359 - qpdf-11.2.0 is available + +* Thu Oct 13 2022 Zdenek Dohnal - 11.1.1-1 +- 2125823 - qpdf-11.1.1 is available + +* Thu Sep 22 2022 Zdenek Dohnal - 11.1.0-1 +- 2125823 - qpdf-11.1.0 is available, move to cmake + +* Thu Sep 22 2022 Zdenek Dohnal - 10.6.3-5 +- use `grep -E` in test suite (bz2127957) + +* Mon Jul 25 2022 Zdenek Dohnal - 10.6.3-4 +- qpdf doesn't depend on pcre since 7.0b1 + +* Fri Jul 22 2022 Fedora Release Engineering - 10.6.3-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild + +* Thu Jul 14 2022 Zdenek Dohnal - 10.6.3-2 +- 2107240 - FIPS breaks pdftopdf and bannertopdf + +* Fri Mar 18 2022 Zdenek Dohnal - 10.6.3-1 +- 2063429 - qpdf-10.6.3 is available + +* Thu Feb 17 2022 Zdenek Dohnal - 10.6.2-1 +- 2053647 - qpdf-10.6.2 is available + +* Mon Feb 14 2022 Zdenek Dohnal - 10.6.1-1 +- 2053647 - qpdf-10.6.1 is available + +* Thu Feb 10 2022 Zdenek Dohnal - 10.6.0-1 +- 2052569 - qpdf-10.6.0 is available + +* Fri Jan 21 2022 Fedora Release Engineering - 10.5.0-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild + +* Wed Jan 05 2022 Zdenek Dohnal - 10.5.0-2 +- add qpdf-manual - now it is in a different archive + +* Mon Jan 03 2022 Zdenek Dohnal - 10.5.0-1 +- 2034671 - qpdf-10.5.0 is available + +* Mon Dec 06 2021 Zdenek Dohnal - 10.4.0-1 +- 2023979 - qpdf-10.4.0 is available + +* Fri Jul 23 2021 Fedora Release Engineering - 10.3.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild + +* Thu May 20 2021 Zdenek Dohnal - 10.3.2-1 +- 1958536 - qpdf-10.3.2 is available + +* Mon Apr 19 2021 Zdenek Dohnal - 10.3.1-2 +- aarch64 specific patches were removed from zlib, so no need for ours +- zlib got downstream patches on s390x, we need to patch qpdf test suite for it + +* Fri Mar 12 2021 Zdenek Dohnal - 10.3.1-1 +- 1937988 - qpdf-10.3.1 is available + +* Thu Mar 11 2021 Zdenek Dohnal - 10.3.0-1 +- 1935799 - qpdf-10.3.0 is available + +* Wed Feb 24 2021 Zdenek Dohnal - 10.2.0-1 +- 1932052 - qpdf-10.2.0 is available + +* Wed Jan 27 2021 Fedora Release Engineering - 10.1.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild + +* Mon Jan 11 2021 Zdenek Dohnal - 10.1.0-1 +- 1912951 - qpdf-10.1.0 is available + +* Mon Nov 23 2020 Zdenek Dohnal - 10.0.4-1 +- 1900262 - qpdf-10.0.4 is available + +* Thu Nov 05 2020 Zdenek Dohnal - 10.0.3-2 +- make is no longer in buildroot by default + +* Mon Nov 02 2020 Zdenek Dohnal - 10.0.3-1 +- 10.0.3 + +* Wed Jul 29 2020 Fedora Release Engineering - 10.0.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Tue Apr 14 2020 Zdenek Dohnal - 10.0.1-1 +- 10.0.1 + +* Wed Mar 25 2020 Jitka Plesnikova - 9.1.1-3 +- Add all perl dependencies for tests + +* Thu Jan 30 2020 Fedora Release Engineering - 9.1.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + +* Mon Jan 27 2020 Zdenek Dohnal - 9.1.1-1 +- 9.1.1 + +* Tue Nov 19 2019 Zdenek Dohnal - 9.1.0-1 +- 9.1.0 + +* Fri Jul 26 2019 Fedora Release Engineering - 8.4.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild + +* Fri May 31 2019 Zdenek Dohnal - 8.4.2-1 +- 8.4.2 + +* Mon Mar 25 2019 Zdenek Dohnal - 8.4.0-1 +- 8.4.0 + +* Sat Feb 02 2019 Fedora Release Engineering - 8.3.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild + +* Mon Jan 14 2019 Zdenek Dohnal - 8.3.0-1 +- 8.3.0 + +* Mon Sep 24 2018 Zdenek Dohnal - 8.2.1-1 +- 8.2.1 + +* Tue Jul 24 2018 Zdenek Dohnal - 8.1.0-4 - correcting license -* Wed Jul 11 2018 Zdenek Dohnal - 7.1.1-6 +* Sat Jul 14 2018 Fedora Release Engineering - 8.1.0-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Wed Jul 11 2018 Zdenek Dohnal - 8.1.0-2 - ship license in correct tag, mention optional change of license -* Mon Apr 16 2018 Zdenek Dohnal - 7.1.1-5 +* Mon Jun 25 2018 Zdenek Dohnal - 8.1.0-1 +- 8.1.0 +- more tests fail because aarch64 zlib optimization - add patch for it + +* Fri May 25 2018 Zdenek Dohnal - 8.0.2-3 +- erase failing tests for aarch64 because of zlib optimization + +* Mon Apr 16 2018 Zdenek Dohnal - CVE-2018-9918 qpdf: stack exhaustion in QPDFObjectHandle and QPDF_Dictionary classes in libqpdf.a [fedora-all] +* Wed Mar 07 2018 Zdenek Dohnal - 8.0.2-1 +- 8.0.2 + +* Mon Mar 05 2018 Zdenek Dohnal - 8.0.1-1 +- 8.0.1 + +* Tue Feb 27 2018 Rex Dieter - 8.0.0-2 +- use %%license, %%ldconfig_scriptlets, %%make_build, %%make_install +- %%files: track files more closely, libqpdf soname in particular + +* Mon Feb 26 2018 Zdenek Dohnal - 8.0.0-1 +- rebase to 8.0.0 + * Mon Feb 19 2018 Zdenek Dohnal - 7.1.1-4 - gcc and gcc-c++ are no longer in buildroot by default diff --git a/sources b/sources index 16230ea..b2d1edc 100644 --- a/sources +++ b/sources @@ -1 +1,2 @@ -SHA512 (qpdf-7.1.1.tar.gz) = a75f988c7dd7ac174bdc981cd3696ca8b539ac6c581e3afecf601dc67277014cb4fe3f0e5cb75a67412cafa4eb645b2fc2d8a0ec203834464baf0c7e80baa0b4 +SHA512 (qpdf-11.8.0-doc.zip) = 5b2748d4b0b0367d4fd2773e697f6e125d92c397b62ee63388bce85c74a051e1b17d487941128927e3493669bd00196caa842eee76db0f05827a650a067b6939 +SHA512 (qpdf-11.8.0.tar.gz) = e558cd4f0066ace73670ead7a49b0343862cdd275bd013eb10cbef6e161a13955101e6d78de8e87bb05a68498c3018152e9d20d61c01dce55d3810e7f5768aa9