diff --git a/README.md b/README.md index 822274db..8b9df7c5 100644 --- a/README.md +++ b/README.md @@ -30,9 +30,7 @@ QPDF requires a C++ compiler that supports C++-11. QPDF depends on the external libraries [zlib](https://www.zlib.net/) and [jpeg](https://www.ijg.org/files/). The [libjpeg-turbo](https://libjpeg-turbo.org/) library is also known to work since it is compatible with the regular jpeg library, and QPDF doesn't use any interfaces that aren't present in the straight jpeg8 API. These are part of every Linux distribution and are readily available. Download information appears in the documentation. For Windows, you can download pre-built binary versions of these libraries for some compilers; see [README-windows.md](README-windows.md) for additional details. -If the optional GnuTLS crypto provider is enabled, -then [GnuTLS](https://www.gnutls.org/) is also required. This is -discussed more in `Crypto providers` below. +Depending on which crypto providers are enabled, then [GnuTLS](https://www.gnutls.org/) and [OpenSSL](https://openssl.org) may also be required. This is discussed more in `Crypto providers` below. # Licensing terms of embedded software @@ -46,6 +44,7 @@ As of version 9.1.0, qpdf can use different crypto implementations. These can be Initially, the following providers are available: * `native`: a native implementation where all the source is embedded in qpdf and no external dependencies are required +* `openssl`: an implementation that can use the OpenSSL (or BoringSSL) libraries to provide crypto; causes libqpdf to link with the OpenSSL library * `gnutls`: an implementation that uses the GnuTLS library to provide crypto; causes libqpdf to link with the GnuTLS library The default behavior is for ./configure to discover which other crypto providers can be supported based on available external libraries, to build all available crypto providers, and to use an external provider as the default over the native one. This behavior can be changed with the following flags to ./configure: diff --git a/autoconf.mk.in b/autoconf.mk.in index 49c81636..cbf57efc 100644 --- a/autoconf.mk.in +++ b/autoconf.mk.in @@ -31,6 +31,7 @@ OBJDUMP=@OBJDUMP@ GENDEPS=@GENDEPS@ LIBTOOL=@LIBTOOL@ USE_CRYPTO_NATIVE=@USE_CRYPTO_NATIVE@ +USE_CRYPTO_OPENSSL=@USE_CRYPTO_OPENSSL@ USE_CRYPTO_GNUTLS=@USE_CRYPTO_GNUTLS@ DOCBOOKX_DTD=@DOCBOOKX_DTD@ FOP=@FOP@ diff --git a/autofiles.sums b/autofiles.sums index 271cb265..e0640f71 100644 --- a/autofiles.sums +++ b/autofiles.sums @@ -1,11 +1,11 @@ -4db55494bcfbd5053f956d435416f30591a59bc24b1c4f4431d0b3da27a54ef7 configure.ac +3fa4ba7aa1286928e542cd2dd221ce43775e03c9689d82edd1cafc80bf51b0a5 configure.ac d3f9ee6f6f0846888d9a10fd3dad2e4b1258be84205426cf04d7cef02d61dad7 aclocal.m4 -2e4cd495837be1b8454a4d8aef541b000988634be89d9c05a9cf5de67dffef5e libqpdf/qpdf/qpdf-config.h.in +b0ce6d1dba8effa47d25154b2bb56eddafc997254a0f3f903cf9b6abffc03616 libqpdf/qpdf/qpdf-config.h.in 5297971a0ef90bcd5563eb3f7127a032bb76d3ae2af7258bf13479caf8983a60 m4/ax_cxx_compile_stdcxx.m4 35bc5c645dc42d47f2daeea06f8f3e767c8a1aee6a35eb2b4854fd2ce66c3413 m4/ax_random_device.m4 6a1e4f8aa2902d7993300660c43e6ee479b4b6781ed7d5ef9c9f9f1cc46623b7 m4/libtool.m4 +26fa3285c35dd6ab00ed1e466ba92a17e4655e01897731ec18a587a4cf5e4f8d m4/lt~obsolete.m4 e77ebba8361b36f14b4d0927173a034b98c5d05049697a9ded84d85eb99a7990 m4/ltoptions.m4 5a6735cda60e0ba0d1b706c0ef648f5d096298da46daefd9cdecdb6a0f4584d3 m4/ltsugar.m4 a27b754709de61575197bf5a980696c98ae49da3f92f0de8ee7f42dd543b7465 m4/ltversion.m4 -26fa3285c35dd6ab00ed1e466ba92a17e4655e01897731ec18a587a4cf5e4f8d m4/lt~obsolete.m4 9fab676fae13feb97d5183a8ed86ae9398c76d21927c28bc59460d230f3e0884 m4/pkg.m4 diff --git a/configure b/configure index dfee048f..9276bac0 100755 --- a/configure +++ b/configure @@ -646,6 +646,9 @@ DEFAULT_CRYPTO USE_CRYPTO_GNUTLS pc_gnutls_LIBS pc_gnutls_CFLAGS +USE_CRYPTO_OPENSSL +pc_openssl_LIBS +pc_openssl_CFLAGS USE_CRYPTO_NATIVE WINDOWS_MAIN_XLINK_FLAGS WINDOWS_WMAIN_XLINK_FLAGS @@ -785,6 +788,7 @@ enable_werror enable_int_warnings enable_implicit_crypto enable_crypto_native +enable_crypto_openssl enable_crypto_gnutls with_default_crypto enable_test_compare_images @@ -818,6 +822,8 @@ pc_zlib_CFLAGS pc_zlib_LIBS pc_libjpeg_CFLAGS pc_libjpeg_LIBS +pc_openssl_CFLAGS +pc_openssl_LIBS pc_gnutls_CFLAGS pc_gnutls_LIBS' @@ -1474,6 +1480,8 @@ Optional Features: are not explicitly requested; true by default --enable-crypto-native whether to include support for native crypto provider + --enable-crypto-openssl whether to include support for the BoringSSL crypto + provider --enable-crypto-gnutls whether to include support for gnutls crypto provider --enable-test-compare-images @@ -1545,6 +1553,10 @@ Some influential environment variables: C compiler flags for pc_libjpeg, overriding pkg-config pc_libjpeg_LIBS linker flags for pc_libjpeg, overriding pkg-config + pc_openssl_CFLAGS + C compiler flags for pc_openssl, overriding pkg-config + pc_openssl_LIBS + linker flags for pc_openssl, overriding pkg-config pc_gnutls_CFLAGS C compiler flags for pc_gnutls, overriding pkg-config pc_gnutls_LIBS @@ -17650,6 +17662,190 @@ fi +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pc_openssl" >&5 +$as_echo_n "checking for pc_openssl... " >&6; } + +if test -n "$pc_openssl_CFLAGS"; then + pkg_cv_pc_openssl_CFLAGS="$pc_openssl_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"openssl\""; } >&5 + ($PKG_CONFIG --exists --print-errors "openssl") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_pc_openssl_CFLAGS=`$PKG_CONFIG --cflags "openssl" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$pc_openssl_LIBS"; then + pkg_cv_pc_openssl_LIBS="$pc_openssl_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"openssl\""; } >&5 + ($PKG_CONFIG --exists --print-errors "openssl") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_pc_openssl_LIBS=`$PKG_CONFIG --libs "openssl" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + pc_openssl_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "openssl" 2>&1` + else + pc_openssl_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "openssl" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$pc_openssl_PKG_ERRORS" >&5 + + OPENSSL_FOUND=0 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + OPENSSL_FOUND=0 +else + pc_openssl_CFLAGS=$pkg_cv_pc_openssl_CFLAGS + pc_openssl_LIBS=$pkg_cv_pc_openssl_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + OPENSSL_FOUND=1 +fi +if test "$OPENSSL_FOUND" = "0"; then + ac_fn_c_check_header_mongrel "$LINENO" "openssl/evp.h" "ac_cv_header_openssl_evp_h" "$ac_includes_default" +if test "x$ac_cv_header_openssl_evp_h" = xyes; then : + OPENSSL_FOUND=1 +else + OPENSSL_FOUND=0 +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing EVP_DigestInit_ex" >&5 +$as_echo_n "checking for library containing EVP_DigestInit_ex... " >&6; } +if ${ac_cv_search_EVP_DigestInit_ex+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char EVP_DigestInit_ex (); +int +main () +{ +return EVP_DigestInit_ex (); + ; + return 0; +} +_ACEOF +for ac_lib in '' openssl; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_EVP_DigestInit_ex=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_EVP_DigestInit_ex+:} false; then : + break +fi +done +if ${ac_cv_search_EVP_DigestInit_ex+:} false; then : + +else + ac_cv_search_EVP_DigestInit_ex=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_EVP_DigestInit_ex" >&5 +$as_echo "$ac_cv_search_EVP_DigestInit_ex" >&6; } +ac_res=$ac_cv_search_EVP_DigestInit_ex +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + OPENSSL_FOUND=1 +else + OPENSSL_FOUND=0 +fi + +fi + +IMPLICIT_OPENSSL=0 +USE_CRYPTO_OPENSSL=0 + +# Check whether --enable-crypto-openssl was given. +if test "${enable_crypto_openssl+set}" = set; then : + enableval=$enable_crypto_openssl; if test "$enableval" = "yes"; then + USE_CRYPTO_OPENSSL=1 + else + USE_CRYPTO_OPENSSL=0 + fi +else + IMPLICIT_OPENSSL=$IMPLICIT_CRYPTO +fi + + +if test "$IMPLICIT_OPENSSL" = "1"; then + USE_CRYPTO_OPENSSL=$OPENSSL_FOUND + if test "$USE_CRYPTO_OPENSSL" = "1"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: enabling openssl crypto provider since openssl is available" >&5 +$as_echo "$as_me: enabling openssl crypto provider since openssl is available" >&6;} + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not enabling openssl crypto provider since openssl was not found" >&5 +$as_echo "$as_me: not enabling openssl crypto provider since openssl was not found" >&6;} + fi +fi + +if test "$USE_CRYPTO_OPENSSL" = "1" -a "$OPENSSL_FOUND" = "0"; then + as_fn_error $? "unable to use requested openssl crypto provider without openssl" "$LINENO" 5 +fi + +if test "$USE_CRYPTO_OPENSSL" = "1"; then + CFLAGS="$CFLAGS $pc_openssl_CFLAGS" + CXXFLAGS="$CXXFLAGS $pc_openssl_CXXFLAGS" + LIBS="$LIBS $pc_openssl_LIBS" + +$as_echo "#define USE_CRYPTO_OPENSSL 1" >>confdefs.h + + DEFAULT_CRYPTO=openssl +elif test "$OPENSSL_FOUND" = "1"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: not linking with openssl even though it is available" >&5 +$as_echo "$as_me: not linking with openssl even though it is available" >&6;} +fi + + + pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pc_gnutls" >&5 $as_echo_n "checking for pc_gnutls... " >&6; } @@ -17858,6 +18054,11 @@ case "$DEFAULT_CRYPTO" in bad_crypto=1 fi ;; + "openssl") + if test "$USE_CRYPTO_OPENSSL" != "1"; then + bad_crypto=1 + fi + ;; "gnutls") if test "$USE_CRYPTO_GNUTLS" != "1"; then bad_crypto=1 diff --git a/configure.ac b/configure.ac index 39f2bfa8..80a748b9 100644 --- a/configure.ac +++ b/configure.ac @@ -513,6 +513,53 @@ if test "$USE_CRYPTO_NATIVE" = "1"; then DEFAULT_CRYPTO=native fi +dnl If the openssl/BoringSSL provider is explicitly requested, require openssl +dnl If the openssl provider is not explicitly disabled, enable it if +dnl openssl is available. If the openssl provider is explicitly +dnl disabled, do not link with openssl even if present. + +PKG_CHECK_MODULES([pc_openssl], [openssl], [OPENSSL_FOUND=1], [OPENSSL_FOUND=0]) +if test "$OPENSSL_FOUND" = "0"; then + AC_CHECK_HEADER([openssl/evp.h],[OPENSSL_FOUND=1],[OPENSSL_FOUND=0]) + AC_SEARCH_LIBS(EVP_DigestInit_ex,openssl,[OPENSSL_FOUND=1],[OPENSSL_FOUND=0]) +fi + +IMPLICIT_OPENSSL=0 +USE_CRYPTO_OPENSSL=0 +AC_SUBST(USE_CRYPTO_OPENSSL) +AC_ARG_ENABLE(crypto-openssl, + AS_HELP_STRING([--enable-crypto-openssl], + [whether to include support for the BoringSSL crypto provider]), + [if test "$enableval" = "yes"; then + USE_CRYPTO_OPENSSL=1 + else + USE_CRYPTO_OPENSSL=0 + fi], + [IMPLICIT_OPENSSL=$IMPLICIT_CRYPTO]) + +if test "$IMPLICIT_OPENSSL" = "1"; then + USE_CRYPTO_OPENSSL=$OPENSSL_FOUND + if test "$USE_CRYPTO_OPENSSL" = "1"; then + AC_MSG_NOTICE(enabling openssl crypto provider since openssl is available) + else + AC_MSG_NOTICE(not enabling openssl crypto provider since openssl was not found) + fi +fi + +if test "$USE_CRYPTO_OPENSSL" = "1" -a "$OPENSSL_FOUND" = "0"; then + AC_MSG_ERROR(unable to use requested openssl crypto provider without openssl) +fi + +if test "$USE_CRYPTO_OPENSSL" = "1"; then + CFLAGS="$CFLAGS $pc_openssl_CFLAGS" + CXXFLAGS="$CXXFLAGS $pc_openssl_CXXFLAGS" + LIBS="$LIBS $pc_openssl_LIBS" + AC_DEFINE([USE_CRYPTO_OPENSSL], 1, [Whether to use the openssl crypto provider]) + DEFAULT_CRYPTO=openssl +elif test "$OPENSSL_FOUND" = "1"; then + AC_MSG_NOTICE(not linking with openssl even though it is available) +fi + dnl If the gnutls provider is explicitly requested, require gnutls. If dnl the gnutls provider is not explicitly disabled, enable it if dnl gnutls is available. If the gnutls provider is explicitly @@ -581,6 +628,11 @@ case "$DEFAULT_CRYPTO" in bad_crypto=1 fi ;; + "openssl") + if test "$USE_CRYPTO_OPENSSL" != "1"; then + bad_crypto=1 + fi + ;; "gnutls") if test "$USE_CRYPTO_GNUTLS" != "1"; then bad_crypto=1 diff --git a/libqpdf/QPDFCryptoProvider.cc b/libqpdf/QPDFCryptoProvider.cc index 5755fcca..b375498d 100644 --- a/libqpdf/QPDFCryptoProvider.cc +++ b/libqpdf/QPDFCryptoProvider.cc @@ -9,6 +9,9 @@ #ifdef USE_CRYPTO_GNUTLS # include #endif +#ifdef USE_CRYPTO_OPENSSL +# include +#endif std::shared_ptr QPDFCryptoProvider::getImpl() @@ -49,6 +52,9 @@ QPDFCryptoProvider::QPDFCryptoProvider() : #endif #ifdef USE_CRYPTO_GNUTLS registerImpl_internal("gnutls"); +#endif +#ifdef USE_CRYPTO_OPENSSL + registerImpl_internal("openssl"); #endif std::string default_crypto; if (! QUtil::get_env("QPDF_CRYPTO_PROVIDER", &default_crypto)) diff --git a/libqpdf/QPDFCrypto_openssl.cc b/libqpdf/QPDFCrypto_openssl.cc new file mode 100644 index 00000000..c226fc9c --- /dev/null +++ b/libqpdf/QPDFCrypto_openssl.cc @@ -0,0 +1,193 @@ +#include + +#include +#include + +#include + + +static void +bad_bits(int bits) +{ + throw std::logic_error( + std::string("unsupported key length: ") + std::to_string(bits)); +} + +static void +check_openssl(int status) +{ + if (status != 1) + { + throw std::runtime_error("openssl error"); + } +} + +QPDFCrypto_openssl::QPDFCrypto_openssl() : + md_ctx(EVP_MD_CTX_new()), cipher_ctx(EVP_CIPHER_CTX_new()) +{ + memset(md_out, 0, sizeof(md_out)); + EVP_MD_CTX_init(md_ctx); + EVP_CIPHER_CTX_init(cipher_ctx); +} + +QPDFCrypto_openssl::~QPDFCrypto_openssl() +{ + EVP_MD_CTX_reset(md_ctx); + EVP_CIPHER_CTX_reset(cipher_ctx); + EVP_CIPHER_CTX_free(cipher_ctx); + EVP_MD_CTX_free(md_ctx); +} + +void +QPDFCrypto_openssl::MD5_init() +{ + check_openssl(EVP_MD_CTX_reset(md_ctx)); + check_openssl(EVP_DigestInit_ex(md_ctx, EVP_md5(), nullptr)); +} + +void +QPDFCrypto_openssl::SHA2_init(int bits) +{ + const EVP_MD* md = EVP_sha512(); + switch (bits) + { + case 256: + md = EVP_sha256(); + break; + case 384: + md = EVP_sha384(); + break; + case 512: + md = EVP_sha512(); + break; + default: + bad_bits(bits); + return; + } + sha2_bits = static_cast(bits); + check_openssl(EVP_MD_CTX_reset(md_ctx)); + check_openssl(EVP_DigestInit_ex(md_ctx, md, nullptr)); +} + +void +QPDFCrypto_openssl::MD5_update(unsigned char const* data, size_t len) +{ + check_openssl(EVP_DigestUpdate(md_ctx, data, len)); +} + +void +QPDFCrypto_openssl::SHA2_update(unsigned char const* data, size_t len) +{ + check_openssl(EVP_DigestUpdate(md_ctx, data, len)); +} + +void +QPDFCrypto_openssl::MD5_finalize() +{ + if (EVP_MD_CTX_md(md_ctx)) + { + check_openssl(EVP_DigestFinal(md_ctx, md_out + 0, nullptr)); + } +} + +void +QPDFCrypto_openssl::SHA2_finalize() +{ + if (EVP_MD_CTX_md(md_ctx)) + { + check_openssl(EVP_DigestFinal(md_ctx, md_out + 0, nullptr)); + } +} + +void +QPDFCrypto_openssl::MD5_digest(MD5_Digest d) +{ + memcpy(d, md_out, sizeof(QPDFCryptoImpl::MD5_Digest)); +} + +std::string +QPDFCrypto_openssl::SHA2_digest() +{ + return std::string(reinterpret_cast(md_out), sha2_bits / 8); +} + +void +QPDFCrypto_openssl::RC4_init(unsigned char const* key_data, int key_len) +{ + check_openssl(EVP_CIPHER_CTX_reset(cipher_ctx)); + if (key_len == -1) + { + key_len = QIntC::to_int( + strlen(reinterpret_cast(key_data))); + } + check_openssl( + EVP_EncryptInit_ex(cipher_ctx, EVP_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)); +} + +void +QPDFCrypto_openssl::rijndael_init( + bool encrypt, unsigned char const* key_data, size_t key_len, + bool cbc_mode, unsigned char* cbc_block) +{ + const EVP_CIPHER* cipher = nullptr; + switch (key_len) + { + case 32: + cipher = cbc_mode ? EVP_aes_256_cbc() : EVP_aes_256_ecb(); + break; + case 24: + cipher = cbc_mode ? EVP_aes_192_cbc() : EVP_aes_192_ecb(); + break; + default: + cipher = cbc_mode ? EVP_aes_128_cbc() : EVP_aes_128_ecb(); + break; + } + + check_openssl(EVP_CIPHER_CTX_reset(cipher_ctx)); + check_openssl( + EVP_CipherInit_ex(cipher_ctx, cipher, nullptr, + key_data, cbc_block, encrypt)); + check_openssl(EVP_CIPHER_CTX_set_padding(cipher_ctx, 0)); +} + +void +QPDFCrypto_openssl::RC4_process( + unsigned char* in_data, size_t len, unsigned char* out_data) +{ + if (nullptr == out_data) + { + out_data = in_data; + } + int out_len = static_cast(len); + check_openssl( + EVP_EncryptUpdate(cipher_ctx, out_data, &out_len, in_data, out_len)); +} + +void +QPDFCrypto_openssl::rijndael_process( + unsigned char* in_data, unsigned char* out_data) +{ + int len = QPDFCryptoImpl::rijndael_buf_size; + check_openssl(EVP_CipherUpdate(cipher_ctx, out_data, &len, in_data, len)); +} + +void +QPDFCrypto_openssl::RC4_finalize() +{ + if (EVP_CIPHER_CTX_cipher(cipher_ctx)) + { + check_openssl(EVP_CIPHER_CTX_reset(cipher_ctx)); + } +} + +void +QPDFCrypto_openssl::rijndael_finalize() +{ + if (EVP_CIPHER_CTX_cipher(cipher_ctx)) + { + check_openssl(EVP_CIPHER_CTX_reset(cipher_ctx)); + } +} diff --git a/libqpdf/build.mk b/libqpdf/build.mk index ac904174..69b1693c 100644 --- a/libqpdf/build.mk +++ b/libqpdf/build.mk @@ -14,6 +14,9 @@ CRYPTO_NATIVE = \ libqpdf/sha2.c \ libqpdf/sha2big.c +CRYPTO_OPENSSL = \ + libqpdf/QPDFCrypto_openssl.cc + CRYPTO_GNUTLS = \ libqpdf/QPDFCrypto_gnutls.cc @@ -97,6 +100,10 @@ ifeq ($(USE_CRYPTO_NATIVE), 1) SRCS_libqpdf += $(CRYPTO_NATIVE) endif +ifeq ($(USE_CRYPTO_OPENSSL), 1) +SRCS_libqpdf += $(CRYPTO_OPENSSL) +endif + ifeq ($(USE_CRYPTO_GNUTLS), 1) SRCS_libqpdf += $(CRYPTO_GNUTLS) endif diff --git a/libqpdf/qpdf/QPDFCrypto_openssl.hh b/libqpdf/qpdf/QPDFCrypto_openssl.hh new file mode 100644 index 00000000..ff8c4831 --- /dev/null +++ b/libqpdf/qpdf/QPDFCrypto_openssl.hh @@ -0,0 +1,50 @@ +#ifndef QPDFCRYPTO_openssl_HH +#define QPDFCRYPTO_openssl_HH + +#include +#include +#ifdef OPENSSL_IS_BORINGSSL +#include +#include +#else +#include +#endif + +class QPDFCrypto_openssl: public QPDFCryptoImpl +{ + public: + QPDFCrypto_openssl(); + + QPDF_DLL + ~QPDFCrypto_openssl() override; + + void MD5_init() override; + void MD5_update(unsigned char const* data, size_t len) override; + void MD5_finalize() override; + void MD5_digest(MD5_Digest) override; + + void RC4_init(unsigned char const* key_data, int key_len = -1) override; + void RC4_process(unsigned char* in_data, size_t len, + unsigned char* out_data = 0) override; + void RC4_finalize() override; + + void SHA2_init(int bits) override; + void SHA2_update(unsigned char const* data, size_t len) override; + void SHA2_finalize() override; + std::string SHA2_digest() override; + + void rijndael_init( + bool encrypt, unsigned char const* key_data, size_t key_len, + bool cbc_mode, unsigned char* cbc_block) override; + void rijndael_process( + unsigned char* in_data, unsigned char* out_data) override; + void rijndael_finalize() override; + + private: + EVP_MD_CTX* const md_ctx; + EVP_CIPHER_CTX* const cipher_ctx; + uint8_t md_out[EVP_MAX_MD_SIZE]; + size_t sha2_bits; +}; + +#endif // QPDFCRYPTO_openssl_HH diff --git a/libqpdf/qpdf/qpdf-config.h.in b/libqpdf/qpdf/qpdf-config.h.in index 75d34c66..c9886b57 100644 --- a/libqpdf/qpdf/qpdf-config.h.in +++ b/libqpdf/qpdf/qpdf-config.h.in @@ -90,6 +90,9 @@ /* Whether to use the native crypto provider */ #undef USE_CRYPTO_NATIVE +/* Whether to use the openssl crypto provider */ +#undef USE_CRYPTO_OPENSSL + /* Whether to use insecure random numbers */ #undef USE_INSECURE_RANDOM