mirror of
https://github.com/qpdf/qpdf.git
synced 2024-09-22 01:59:10 +00:00
Implement gnutls crypto provider (fixes #218)
Thanks to Zdenek Dohnal <zdohnal@redhat.com> for contributing the code used for the gnutls crypto provider.
This commit is contained in:
parent
cc14523440
commit
88bedb41fe
@ -31,6 +31,7 @@ OBJDUMP=@OBJDUMP@
|
|||||||
GENDEPS=@GENDEPS@
|
GENDEPS=@GENDEPS@
|
||||||
LIBTOOL=@LIBTOOL@
|
LIBTOOL=@LIBTOOL@
|
||||||
USE_CRYPTO_NATIVE=@USE_CRYPTO_NATIVE@
|
USE_CRYPTO_NATIVE=@USE_CRYPTO_NATIVE@
|
||||||
|
USE_CRYPTO_GNUTLS=@USE_CRYPTO_GNUTLS@
|
||||||
DOCBOOKX_DTD=@DOCBOOKX_DTD@
|
DOCBOOKX_DTD=@DOCBOOKX_DTD@
|
||||||
FOP=@FOP@
|
FOP=@FOP@
|
||||||
XSLTPROC=@XSLTPROC@
|
XSLTPROC=@XSLTPROC@
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
2b5c5a808c353b8df9e28e8cfb1e7d37114a2cad37eaede5bfe4354acae804d0 configure.ac
|
97f3ed3cd8b491f0ceeb57baa40f4ed9c4be188692da1d13c93ef318c45cc4ae configure.ac
|
||||||
d3f9ee6f6f0846888d9a10fd3dad2e4b1258be84205426cf04d7cef02d61dad7 aclocal.m4
|
d3f9ee6f6f0846888d9a10fd3dad2e4b1258be84205426cf04d7cef02d61dad7 aclocal.m4
|
||||||
7fc840fce5d372e92aa676e0040213a0f239cc8c01b6d6ef53c82043ceda571a libqpdf/qpdf/qpdf-config.h.in
|
2e4cd495837be1b8454a4d8aef541b000988634be89d9c05a9cf5de67dffef5e libqpdf/qpdf/qpdf-config.h.in
|
||||||
5297971a0ef90bcd5563eb3f7127a032bb76d3ae2af7258bf13479caf8983a60 m4/ax_cxx_compile_stdcxx.m4
|
5297971a0ef90bcd5563eb3f7127a032bb76d3ae2af7258bf13479caf8983a60 m4/ax_cxx_compile_stdcxx.m4
|
||||||
35bc5c645dc42d47f2daeea06f8f3e767c8a1aee6a35eb2b4854fd2ce66c3413 m4/ax_random_device.m4
|
35bc5c645dc42d47f2daeea06f8f3e767c8a1aee6a35eb2b4854fd2ce66c3413 m4/ax_random_device.m4
|
||||||
37f8897d5f68d7d484e5457832a8f190ddb7507fa2a467cb7ee2be40a4364643 m4/libtool.m4
|
37f8897d5f68d7d484e5457832a8f190ddb7507fa2a467cb7ee2be40a4364643 m4/libtool.m4
|
||||||
|
135
configure
vendored
135
configure
vendored
@ -643,6 +643,9 @@ DOCBOOK_XHTML
|
|||||||
SHOW_FAILED_TEST_OUTPUT
|
SHOW_FAILED_TEST_OUTPUT
|
||||||
QPDF_SKIP_TEST_COMPARE_IMAGES
|
QPDF_SKIP_TEST_COMPARE_IMAGES
|
||||||
DEFAULT_CRYPTO
|
DEFAULT_CRYPTO
|
||||||
|
USE_CRYPTO_GNUTLS
|
||||||
|
pc_gnutls_LIBS
|
||||||
|
pc_gnutls_CFLAGS
|
||||||
USE_CRYPTO_NATIVE
|
USE_CRYPTO_NATIVE
|
||||||
CXXWFLAGS
|
CXXWFLAGS
|
||||||
WFLAGS
|
WFLAGS
|
||||||
@ -780,6 +783,7 @@ enable_werror
|
|||||||
enable_int_warnings
|
enable_int_warnings
|
||||||
enable_implicit_crypto
|
enable_implicit_crypto
|
||||||
enable_crypto_native
|
enable_crypto_native
|
||||||
|
enable_crypto_gnutls
|
||||||
with_default_crypto
|
with_default_crypto
|
||||||
enable_test_compare_images
|
enable_test_compare_images
|
||||||
enable_show_failed_test_output
|
enable_show_failed_test_output
|
||||||
@ -811,7 +815,9 @@ PKG_CONFIG_LIBDIR
|
|||||||
pc_zlib_CFLAGS
|
pc_zlib_CFLAGS
|
||||||
pc_zlib_LIBS
|
pc_zlib_LIBS
|
||||||
pc_libjpeg_CFLAGS
|
pc_libjpeg_CFLAGS
|
||||||
pc_libjpeg_LIBS'
|
pc_libjpeg_LIBS
|
||||||
|
pc_gnutls_CFLAGS
|
||||||
|
pc_gnutls_LIBS'
|
||||||
|
|
||||||
|
|
||||||
# Initialize some variables set by options.
|
# Initialize some variables set by options.
|
||||||
@ -1466,6 +1472,8 @@ Optional Features:
|
|||||||
are not explicitly requested; true by default
|
are not explicitly requested; true by default
|
||||||
--enable-crypto-native whether to include support for native crypto
|
--enable-crypto-native whether to include support for native crypto
|
||||||
provider
|
provider
|
||||||
|
--enable-crypto-gnutls whether to include support for gnutls crypto
|
||||||
|
provider
|
||||||
--enable-test-compare-images
|
--enable-test-compare-images
|
||||||
whether to compare images in test suite; disabled by
|
whether to compare images in test suite; disabled by
|
||||||
default, enabling requires ghostscript and tiffcmp
|
default, enabling requires ghostscript and tiffcmp
|
||||||
@ -1535,6 +1543,10 @@ Some influential environment variables:
|
|||||||
C compiler flags for pc_libjpeg, overriding pkg-config
|
C compiler flags for pc_libjpeg, overriding pkg-config
|
||||||
pc_libjpeg_LIBS
|
pc_libjpeg_LIBS
|
||||||
linker flags for pc_libjpeg, overriding pkg-config
|
linker flags for pc_libjpeg, overriding pkg-config
|
||||||
|
pc_gnutls_CFLAGS
|
||||||
|
C compiler flags for pc_gnutls, overriding pkg-config
|
||||||
|
pc_gnutls_LIBS
|
||||||
|
linker flags for pc_gnutls, overriding pkg-config
|
||||||
|
|
||||||
Use these variables to override the choices made by `configure' or to help
|
Use these variables to override the choices made by `configure' or to help
|
||||||
it to find libraries and programs with nonstandard names/locations.
|
it to find libraries and programs with nonstandard names/locations.
|
||||||
@ -17625,6 +17637,122 @@ $as_echo "#define USE_CRYPTO_NATIVE 1" >>confdefs.h
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
pkg_failed=no
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pc_gnutls" >&5
|
||||||
|
$as_echo_n "checking for pc_gnutls... " >&6; }
|
||||||
|
|
||||||
|
if test -n "$pc_gnutls_CFLAGS"; then
|
||||||
|
pkg_cv_pc_gnutls_CFLAGS="$pc_gnutls_CFLAGS"
|
||||||
|
elif test -n "$PKG_CONFIG"; then
|
||||||
|
if test -n "$PKG_CONFIG" && \
|
||||||
|
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gnutls\""; } >&5
|
||||||
|
($PKG_CONFIG --exists --print-errors "gnutls") 2>&5
|
||||||
|
ac_status=$?
|
||||||
|
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||||
|
test $ac_status = 0; }; then
|
||||||
|
pkg_cv_pc_gnutls_CFLAGS=`$PKG_CONFIG --cflags "gnutls" 2>/dev/null`
|
||||||
|
test "x$?" != "x0" && pkg_failed=yes
|
||||||
|
else
|
||||||
|
pkg_failed=yes
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
pkg_failed=untried
|
||||||
|
fi
|
||||||
|
if test -n "$pc_gnutls_LIBS"; then
|
||||||
|
pkg_cv_pc_gnutls_LIBS="$pc_gnutls_LIBS"
|
||||||
|
elif test -n "$PKG_CONFIG"; then
|
||||||
|
if test -n "$PKG_CONFIG" && \
|
||||||
|
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gnutls\""; } >&5
|
||||||
|
($PKG_CONFIG --exists --print-errors "gnutls") 2>&5
|
||||||
|
ac_status=$?
|
||||||
|
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||||
|
test $ac_status = 0; }; then
|
||||||
|
pkg_cv_pc_gnutls_LIBS=`$PKG_CONFIG --libs "gnutls" 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_gnutls_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gnutls" 2>&1`
|
||||||
|
else
|
||||||
|
pc_gnutls_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gnutls" 2>&1`
|
||||||
|
fi
|
||||||
|
# Put the nasty error message in config.log where it belongs
|
||||||
|
echo "$pc_gnutls_PKG_ERRORS" >&5
|
||||||
|
|
||||||
|
GNUTLS_FOUND=0
|
||||||
|
elif test $pkg_failed = untried; then
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||||
|
$as_echo "no" >&6; }
|
||||||
|
GNUTLS_FOUND=0
|
||||||
|
else
|
||||||
|
pc_gnutls_CFLAGS=$pkg_cv_pc_gnutls_CFLAGS
|
||||||
|
pc_gnutls_LIBS=$pkg_cv_pc_gnutls_LIBS
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||||
|
$as_echo "yes" >&6; }
|
||||||
|
GNUTLS_FOUND=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
IMPLICIT_GNUTLS=0
|
||||||
|
USE_CRYPTO_GNUTLS=0
|
||||||
|
|
||||||
|
# Check whether --enable-crypto-gnutls was given.
|
||||||
|
if test "${enable_crypto_gnutls+set}" = set; then :
|
||||||
|
enableval=$enable_crypto_gnutls; if test "$enableval" = "yes"; then
|
||||||
|
USE_CRYPTO_GNUTLS=1
|
||||||
|
else
|
||||||
|
USE_CRYPTO_GNUTLS=0
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
IMPLICIT_GNUTLS=$IMPLICIT_CRYPTO
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
if test "$IMPLICIT_GNUTLS" = "1"; then
|
||||||
|
USE_CRYPTO_GNUTLS=$GNUTLS_FOUND
|
||||||
|
if test "$USE_CRYPTO_GNUTLS" = "1"; then
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: enabling gnutls crypto provider since gnutls is available" >&5
|
||||||
|
$as_echo "$as_me: enabling gnutls crypto provider since gnutls is available" >&6;}
|
||||||
|
else
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: not enabling gnutls crypto provider since gnutls was not found" >&5
|
||||||
|
$as_echo "$as_me: not enabling gnutls crypto provider since gnutls was not found" >&6;}
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "$USE_CRYPTO_GNUTLS" = "1" -a "$GNUTLS_FOUND" = "0"; then
|
||||||
|
as_fn_error $? "unable to use requested gnutls crypto provider without gnutls" "$LINENO" 5
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "$USE_CRYPTO_GNUTLS" = "1"; then
|
||||||
|
CFLAGS="$CFLAGS $pc_gnutls_CFLAGS"
|
||||||
|
CXXFLAGS="$CXXFLAGS $pc_gnutls_CXXFLAGS"
|
||||||
|
LIBS="$LIBS $pc_gnutls_LIBS"
|
||||||
|
|
||||||
|
$as_echo "#define USE_CRYPTO_GNUTLS 1" >>confdefs.h
|
||||||
|
|
||||||
|
DEFAULT_CRYPTO=gnutls
|
||||||
|
elif test "$GNUTLS_FOUND" = "1"; then
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: not linking with gnutls even though it is available" >&5
|
||||||
|
$as_echo "$as_me: not linking with gnutls even though it is available" >&6;}
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking which crypto to use by default" >&5
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking which crypto to use by default" >&5
|
||||||
$as_echo_n "checking which crypto to use by default... " >&6; }
|
$as_echo_n "checking which crypto to use by default... " >&6; }
|
||||||
|
|
||||||
@ -17650,6 +17778,11 @@ case "$DEFAULT_CRYPTO" in
|
|||||||
bad_crypto=1
|
bad_crypto=1
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
"gnutls")
|
||||||
|
if test "$USE_CRYPTO_GNUTLS" != "1"; then
|
||||||
|
bad_crypto=1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
bad_crypto=1
|
bad_crypto=1
|
||||||
;;
|
;;
|
||||||
|
48
configure.ac
48
configure.ac
@ -506,6 +506,49 @@ if test "$USE_CRYPTO_NATIVE" = "1"; then
|
|||||||
DEFAULT_CRYPTO=native
|
DEFAULT_CRYPTO=native
|
||||||
fi
|
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
|
||||||
|
dnl disabled, do not link with gnutls even if present.
|
||||||
|
|
||||||
|
PKG_CHECK_MODULES([pc_gnutls], [gnutls], [GNUTLS_FOUND=1], [GNUTLS_FOUND=0])
|
||||||
|
|
||||||
|
IMPLICIT_GNUTLS=0
|
||||||
|
USE_CRYPTO_GNUTLS=0
|
||||||
|
AC_SUBST(USE_CRYPTO_GNUTLS)
|
||||||
|
AC_ARG_ENABLE(crypto-gnutls,
|
||||||
|
AS_HELP_STRING([--enable-crypto-gnutls],
|
||||||
|
[whether to include support for gnutls crypto provider]),
|
||||||
|
[if test "$enableval" = "yes"; then
|
||||||
|
USE_CRYPTO_GNUTLS=1
|
||||||
|
else
|
||||||
|
USE_CRYPTO_GNUTLS=0
|
||||||
|
fi],
|
||||||
|
[IMPLICIT_GNUTLS=$IMPLICIT_CRYPTO])
|
||||||
|
|
||||||
|
if test "$IMPLICIT_GNUTLS" = "1"; then
|
||||||
|
USE_CRYPTO_GNUTLS=$GNUTLS_FOUND
|
||||||
|
if test "$USE_CRYPTO_GNUTLS" = "1"; then
|
||||||
|
AC_MSG_NOTICE(enabling gnutls crypto provider since gnutls is available)
|
||||||
|
else
|
||||||
|
AC_MSG_NOTICE(not enabling gnutls crypto provider since gnutls was not found)
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "$USE_CRYPTO_GNUTLS" = "1" -a "$GNUTLS_FOUND" = "0"; then
|
||||||
|
AC_MSG_ERROR(unable to use requested gnutls crypto provider without gnutls)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "$USE_CRYPTO_GNUTLS" = "1"; then
|
||||||
|
CFLAGS="$CFLAGS $pc_gnutls_CFLAGS"
|
||||||
|
CXXFLAGS="$CXXFLAGS $pc_gnutls_CXXFLAGS"
|
||||||
|
LIBS="$LIBS $pc_gnutls_LIBS"
|
||||||
|
AC_DEFINE([USE_CRYPTO_GNUTLS], 1, [Whether to use the gnutls crypto provider])
|
||||||
|
DEFAULT_CRYPTO=gnutls
|
||||||
|
elif test "$GNUTLS_FOUND" = "1"; then
|
||||||
|
AC_MSG_NOTICE(not linking with gnutls even though it is available)
|
||||||
|
fi
|
||||||
|
|
||||||
dnl Allow the default crypto provider to be specified explicitly.
|
dnl Allow the default crypto provider to be specified explicitly.
|
||||||
|
|
||||||
AC_MSG_CHECKING(which crypto to use by default)
|
AC_MSG_CHECKING(which crypto to use by default)
|
||||||
@ -527,6 +570,11 @@ case "$DEFAULT_CRYPTO" in
|
|||||||
bad_crypto=1
|
bad_crypto=1
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
"gnutls")
|
||||||
|
if test "$USE_CRYPTO_GNUTLS" != "1"; then
|
||||||
|
bad_crypto=1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
bad_crypto=1
|
bad_crypto=1
|
||||||
;;
|
;;
|
||||||
|
@ -5,6 +5,9 @@
|
|||||||
#ifdef USE_CRYPTO_NATIVE
|
#ifdef USE_CRYPTO_NATIVE
|
||||||
# include <qpdf/QPDFCrypto_native.hh>
|
# include <qpdf/QPDFCrypto_native.hh>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef USE_CRYPTO_GNUTLS
|
||||||
|
# include <qpdf/QPDFCrypto_gnutls.hh>
|
||||||
|
#endif
|
||||||
|
|
||||||
std::shared_ptr<QPDFCryptoImpl>
|
std::shared_ptr<QPDFCryptoImpl>
|
||||||
QPDFCryptoProvider::getImpl()
|
QPDFCryptoProvider::getImpl()
|
||||||
@ -42,6 +45,9 @@ QPDFCryptoProvider::QPDFCryptoProvider() :
|
|||||||
{
|
{
|
||||||
#ifdef USE_CRYPTO_NATIVE
|
#ifdef USE_CRYPTO_NATIVE
|
||||||
registerImpl_internal<QPDFCrypto_native>("native");
|
registerImpl_internal<QPDFCrypto_native>("native");
|
||||||
|
#endif
|
||||||
|
#ifdef USE_CRYPTO_GNUTLS
|
||||||
|
registerImpl_internal<QPDFCrypto_gnutls>("gnutls");
|
||||||
#endif
|
#endif
|
||||||
setDefaultProvider_internal(DEFAULT_CRYPTO);
|
setDefaultProvider_internal(DEFAULT_CRYPTO);
|
||||||
}
|
}
|
||||||
|
277
libqpdf/QPDFCrypto_gnutls.cc
Normal file
277
libqpdf/QPDFCrypto_gnutls.cc
Normal file
@ -0,0 +1,277 @@
|
|||||||
|
#include <qpdf/QPDFCrypto_gnutls.hh>
|
||||||
|
#include <qpdf/QIntC.hh>
|
||||||
|
#include <qpdf/QUtil.hh>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
QPDFCrypto_gnutls::QPDFCrypto_gnutls() :
|
||||||
|
hash_ctx(nullptr),
|
||||||
|
cipher_ctx(nullptr),
|
||||||
|
sha2_bits(0),
|
||||||
|
encrypt(false),
|
||||||
|
cbc_mode(false),
|
||||||
|
aes_key_data(nullptr),
|
||||||
|
aes_key_len(0)
|
||||||
|
{
|
||||||
|
memset(digest, 0, sizeof(digest));
|
||||||
|
}
|
||||||
|
|
||||||
|
QPDFCrypto_gnutls::~QPDFCrypto_gnutls()
|
||||||
|
{
|
||||||
|
if (this->hash_ctx)
|
||||||
|
{
|
||||||
|
gnutls_hash_deinit(this->hash_ctx, digest);
|
||||||
|
}
|
||||||
|
if (cipher_ctx)
|
||||||
|
{
|
||||||
|
gnutls_cipher_deinit(this->cipher_ctx);
|
||||||
|
}
|
||||||
|
this->aes_key_data = nullptr;
|
||||||
|
this->aes_key_len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
QPDFCrypto_gnutls::MD5_init()
|
||||||
|
{
|
||||||
|
MD5_finalize();
|
||||||
|
int code = gnutls_hash_init(&this->hash_ctx, GNUTLS_DIG_MD5);
|
||||||
|
if (code < 0)
|
||||||
|
{
|
||||||
|
this->hash_ctx = nullptr;
|
||||||
|
throw std::runtime_error(
|
||||||
|
std::string("gnutls: MD5 error: ") +
|
||||||
|
std::string(gnutls_strerror(code)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
QPDFCrypto_gnutls::MD5_update(unsigned char const* data, size_t len)
|
||||||
|
{
|
||||||
|
gnutls_hash(this->hash_ctx, data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
QPDFCrypto_gnutls::MD5_finalize()
|
||||||
|
{
|
||||||
|
if (this->hash_ctx)
|
||||||
|
{
|
||||||
|
gnutls_hash_deinit(this->hash_ctx, this->digest);
|
||||||
|
this->hash_ctx = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
QPDFCrypto_gnutls::MD5_digest(MD5_Digest d)
|
||||||
|
{
|
||||||
|
memcpy(d, this->digest, sizeof(MD5_Digest));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
QPDFCrypto_gnutls::RC4_init(unsigned char const* key_data, int key_len)
|
||||||
|
{
|
||||||
|
RC4_finalize();
|
||||||
|
if (key_len == -1)
|
||||||
|
{
|
||||||
|
key_len = QIntC::to_int(
|
||||||
|
strlen(reinterpret_cast<char const*>(key_data)));
|
||||||
|
}
|
||||||
|
gnutls_datum_t key;
|
||||||
|
key.data = const_cast<unsigned char*>(key_data);
|
||||||
|
key.size = QIntC::to_uint(key_len);
|
||||||
|
|
||||||
|
int code = gnutls_cipher_init(
|
||||||
|
&this->cipher_ctx, GNUTLS_CIPHER_ARCFOUR_128, &key, nullptr);
|
||||||
|
if (code < 0)
|
||||||
|
{
|
||||||
|
this->cipher_ctx = nullptr;
|
||||||
|
throw std::runtime_error(
|
||||||
|
std::string("gnutls: RC4 error: ") +
|
||||||
|
std::string(gnutls_strerror(code)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
QPDFCrypto_gnutls::RC4_process(unsigned char* in_data, size_t len,
|
||||||
|
unsigned char* out_data)
|
||||||
|
{
|
||||||
|
if (nullptr == out_data)
|
||||||
|
{
|
||||||
|
out_data = in_data;
|
||||||
|
}
|
||||||
|
gnutls_cipher_encrypt2(this->cipher_ctx, in_data, len, out_data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
QPDFCrypto_gnutls::RC4_finalize()
|
||||||
|
{
|
||||||
|
if (this->cipher_ctx)
|
||||||
|
{
|
||||||
|
gnutls_cipher_deinit(this->cipher_ctx);
|
||||||
|
this->cipher_ctx = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
QPDFCrypto_gnutls::SHA2_init(int bits)
|
||||||
|
{
|
||||||
|
SHA2_finalize();
|
||||||
|
gnutls_digest_algorithm_t alg = GNUTLS_DIG_UNKNOWN;
|
||||||
|
switch (bits)
|
||||||
|
{
|
||||||
|
case 256:
|
||||||
|
alg = GNUTLS_DIG_SHA256;
|
||||||
|
break;
|
||||||
|
case 384:
|
||||||
|
alg = GNUTLS_DIG_SHA384;
|
||||||
|
break;
|
||||||
|
case 512:
|
||||||
|
alg = GNUTLS_DIG_SHA512;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
badBits();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
this->sha2_bits = bits;
|
||||||
|
int code = gnutls_hash_init(&this->hash_ctx, alg);
|
||||||
|
if (code < 0)
|
||||||
|
{
|
||||||
|
this->hash_ctx = nullptr;
|
||||||
|
throw std::runtime_error(
|
||||||
|
std::string("gnutls: SHA") + QUtil::int_to_string(bits) +
|
||||||
|
" error: " + std::string(gnutls_strerror(code)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
QPDFCrypto_gnutls::SHA2_update(unsigned char const* data, size_t len)
|
||||||
|
{
|
||||||
|
gnutls_hash(this->hash_ctx, data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
QPDFCrypto_gnutls::SHA2_finalize()
|
||||||
|
{
|
||||||
|
if (this->hash_ctx)
|
||||||
|
{
|
||||||
|
gnutls_hash_deinit(this->hash_ctx, this->digest);
|
||||||
|
this->hash_ctx = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
QPDFCrypto_gnutls::SHA2_digest()
|
||||||
|
{
|
||||||
|
std::string result;
|
||||||
|
switch (this->sha2_bits)
|
||||||
|
{
|
||||||
|
case 256:
|
||||||
|
result = std::string(reinterpret_cast<char*>(this->digest), 32);
|
||||||
|
break;
|
||||||
|
case 384:
|
||||||
|
result = std::string(reinterpret_cast<char*>(this->digest), 48);
|
||||||
|
break;
|
||||||
|
case 512:
|
||||||
|
result = std::string(reinterpret_cast<char*>(this->digest), 64);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
badBits();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
QPDFCrypto_gnutls::rijndael_init(
|
||||||
|
bool encrypt, unsigned char const* key_data, size_t key_len,
|
||||||
|
bool cbc_mode, unsigned char* cbc_block)
|
||||||
|
{
|
||||||
|
rijndael_finalize();
|
||||||
|
this->encrypt = encrypt;
|
||||||
|
this->cbc_mode = cbc_mode;
|
||||||
|
if (! cbc_mode)
|
||||||
|
{
|
||||||
|
// Save the key so we can re-initialize.
|
||||||
|
this->aes_key_data = key_data;
|
||||||
|
this->aes_key_len = key_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
gnutls_cipher_algorithm_t alg = GNUTLS_CIPHER_UNKNOWN;
|
||||||
|
gnutls_datum_t cipher_key;
|
||||||
|
gnutls_datum_t iv;
|
||||||
|
|
||||||
|
cipher_key.data = const_cast<unsigned char*>(key_data);
|
||||||
|
|
||||||
|
switch(key_len)
|
||||||
|
{
|
||||||
|
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 = QIntC::to_uint(gnutls_cipher_get_key_size(alg));
|
||||||
|
|
||||||
|
iv.data = cbc_block;
|
||||||
|
iv.size = rijndael_buf_size;
|
||||||
|
|
||||||
|
int code = gnutls_cipher_init(&this->cipher_ctx, alg, &cipher_key, &iv);
|
||||||
|
if (code < 0)
|
||||||
|
{
|
||||||
|
this->cipher_ctx = nullptr;
|
||||||
|
throw std::runtime_error(
|
||||||
|
std::string("gnutls: AES error: ") +
|
||||||
|
std::string(gnutls_strerror(code)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
QPDFCrypto_gnutls::rijndael_process(unsigned char* in_data,
|
||||||
|
unsigned char* out_data)
|
||||||
|
{
|
||||||
|
if (this->encrypt)
|
||||||
|
{
|
||||||
|
gnutls_cipher_encrypt2(this->cipher_ctx,
|
||||||
|
in_data, rijndael_buf_size,
|
||||||
|
out_data, rijndael_buf_size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gnutls_cipher_decrypt2(this->cipher_ctx,
|
||||||
|
in_data, rijndael_buf_size,
|
||||||
|
out_data, rijndael_buf_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gnutls doesn't support AES in ECB (non-CBC) mode, but the
|
||||||
|
// result is the same as if you just reset the cbc block to all
|
||||||
|
// zeroes each time. We jump through a few hoops here to make this
|
||||||
|
// work.
|
||||||
|
if (! this->cbc_mode)
|
||||||
|
{
|
||||||
|
static unsigned char zeroes[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||||
|
rijndael_init(this->encrypt, this->aes_key_data, this->aes_key_len,
|
||||||
|
false, zeroes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
QPDFCrypto_gnutls::rijndael_finalize()
|
||||||
|
{
|
||||||
|
if (this->cipher_ctx)
|
||||||
|
{
|
||||||
|
gnutls_cipher_deinit(this->cipher_ctx);
|
||||||
|
this->cipher_ctx = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
QPDFCrypto_gnutls::badBits()
|
||||||
|
{
|
||||||
|
throw std::logic_error("SHA2 (gnutls) has bits != 256, 384, or 512");
|
||||||
|
}
|
@ -14,6 +14,9 @@ CRYPTO_NATIVE = \
|
|||||||
libqpdf/sha2.c \
|
libqpdf/sha2.c \
|
||||||
libqpdf/sha2big.c
|
libqpdf/sha2big.c
|
||||||
|
|
||||||
|
CRYPTO_GNUTLS = \
|
||||||
|
libqpdf/QPDFCrypto_gnutls.cc
|
||||||
|
|
||||||
SRCS_libqpdf = \
|
SRCS_libqpdf = \
|
||||||
libqpdf/BitStream.cc \
|
libqpdf/BitStream.cc \
|
||||||
libqpdf/BitWriter.cc \
|
libqpdf/BitWriter.cc \
|
||||||
@ -94,6 +97,10 @@ ifeq ($(USE_CRYPTO_NATIVE), 1)
|
|||||||
SRCS_libqpdf += $(CRYPTO_NATIVE)
|
SRCS_libqpdf += $(CRYPTO_NATIVE)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(USE_CRYPTO_GNUTLS), 1)
|
||||||
|
SRCS_libqpdf += $(CRYPTO_GNUTLS)
|
||||||
|
endif
|
||||||
|
|
||||||
# -----
|
# -----
|
||||||
|
|
||||||
CCSRCS_libqpdf = $(filter %.cc,$(SRCS_libqpdf))
|
CCSRCS_libqpdf = $(filter %.cc,$(SRCS_libqpdf))
|
||||||
|
53
libqpdf/qpdf/QPDFCrypto_gnutls.hh
Normal file
53
libqpdf/qpdf/QPDFCrypto_gnutls.hh
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#ifndef QPDFCRYPTO_GNUTLS_HH
|
||||||
|
#define QPDFCRYPTO_GNUTLS_HH
|
||||||
|
|
||||||
|
#include <qpdf/DLL.h>
|
||||||
|
#include <qpdf/QPDFCryptoImpl.hh>
|
||||||
|
#include <memory>
|
||||||
|
#include <gnutls/gnutls.h>
|
||||||
|
#include <gnutls/crypto.h>
|
||||||
|
|
||||||
|
class QPDFCrypto_gnutls: public QPDFCryptoImpl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QPDFCrypto_gnutls();
|
||||||
|
|
||||||
|
QPDF_DLL
|
||||||
|
virtual ~QPDFCrypto_gnutls();
|
||||||
|
|
||||||
|
virtual void MD5_init();
|
||||||
|
virtual void MD5_update(unsigned char const* data, size_t len);
|
||||||
|
virtual void MD5_finalize();
|
||||||
|
virtual void MD5_digest(MD5_Digest);
|
||||||
|
|
||||||
|
virtual void RC4_init(unsigned char const* key_data, int key_len = -1);
|
||||||
|
virtual void RC4_process(unsigned char* in_data, size_t len,
|
||||||
|
unsigned char* out_data = 0);
|
||||||
|
virtual void RC4_finalize();
|
||||||
|
|
||||||
|
virtual void SHA2_init(int bits);
|
||||||
|
virtual void SHA2_update(unsigned char const* data, size_t len);
|
||||||
|
virtual void SHA2_finalize();
|
||||||
|
virtual std::string SHA2_digest();
|
||||||
|
|
||||||
|
virtual void rijndael_init(
|
||||||
|
bool encrypt, unsigned char const* key_data, size_t key_len,
|
||||||
|
bool cbc_mode, unsigned char* cbc_block);
|
||||||
|
virtual void rijndael_process(
|
||||||
|
unsigned char* in_data, unsigned char* out_data);
|
||||||
|
virtual void rijndael_finalize();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void badBits();
|
||||||
|
|
||||||
|
gnutls_hash_hd_t hash_ctx;
|
||||||
|
gnutls_cipher_hd_t cipher_ctx;
|
||||||
|
int sha2_bits;
|
||||||
|
bool encrypt;
|
||||||
|
bool cbc_mode;
|
||||||
|
char digest[64];
|
||||||
|
unsigned char const* aes_key_data;
|
||||||
|
size_t aes_key_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // QPDFCRYPTO_GNUTLS_HH
|
@ -84,6 +84,9 @@
|
|||||||
/* Define to 1 if you have the ANSI C header files. */
|
/* Define to 1 if you have the ANSI C header files. */
|
||||||
#undef STDC_HEADERS
|
#undef STDC_HEADERS
|
||||||
|
|
||||||
|
/* Whether to use the gnutls crypto provider */
|
||||||
|
#undef USE_CRYPTO_GNUTLS
|
||||||
|
|
||||||
/* Whether to use the native crypto provider */
|
/* Whether to use the native crypto provider */
|
||||||
#undef USE_CRYPTO_NATIVE
|
#undef USE_CRYPTO_NATIVE
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user