|
|
f1f986 |
diff --git a/configure.ac b/configure.ac
|
|
|
f1f986 |
index a9f0316..6ff59ef 100644
|
|
|
f1f986 |
--- a/configure.ac
|
|
|
f1f986 |
+++ b/configure.ac
|
|
|
f1f986 |
@@ -348,6 +348,36 @@ AC_ARG_ENABLE(show-failed-test-output,
|
|
|
f1f986 |
fi],
|
|
|
f1f986 |
[SHOW_FAILED_TEST_OUTPUT=0])
|
|
|
f1f986 |
|
|
|
f1f986 |
+AC_PATH_TOOL(PKGCONFIG, pkg-config)
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+AC_MSG_CHECKING(if cryptography will be supplied by GNU TLS)
|
|
|
f1f986 |
+AC_ARG_ENABLE(gnutls,
|
|
|
f1f986 |
+ AS_HELP_STRING([--enable-gnutls],
|
|
|
f1f986 |
+ [enable cryptography by GNUTLS]),
|
|
|
f1f986 |
+ [if test "$enableval" = "yes"; then
|
|
|
f1f986 |
+ if test "x$PKGCONFIG" != x ; then
|
|
|
f1f986 |
+ AC_TRY_COMPILE([
|
|
|
f1f986 |
+ #include <gnutls/crypto.h>], , , AC_MSG_ERROR([GNU TLS development headers are needed.]))
|
|
|
f1f986 |
+ GNUTLSFLAGS=`pkg-config --cflags gnutls`
|
|
|
f1f986 |
+ GNUTLSLIBS=`pkg-config --libs gnutls`
|
|
|
f1f986 |
+ LIBS="$LIBS $GNUTLSLIBS"
|
|
|
f1f986 |
+ CPPFLAGS="$CPPFLAGS $GNUTLSFLAGS"
|
|
|
f1f986 |
+ AC_DEFINE([HAVE_GNUTLS], [1], [If cryptography will be supplied by GNU TLS])
|
|
|
f1f986 |
+ HAVE_GNUTLS=1
|
|
|
f1f986 |
+ else
|
|
|
f1f986 |
+ HAVE_GNUTLS=0
|
|
|
f1f986 |
+ AC_MSG_ERROR([pkg-config is needed to configure compilation with GNU TLS.])
|
|
|
f1f986 |
+ fi
|
|
|
f1f986 |
+ else
|
|
|
f1f986 |
+ HAVE_GNUTLS=0
|
|
|
f1f986 |
+ fi],
|
|
|
f1f986 |
+ [HAVE_GNUTLS=0])
|
|
|
f1f986 |
+if test "$HAVE_GNUTLS" = "1" ; then
|
|
|
f1f986 |
+ AC_MSG_RESULT(yes)
|
|
|
f1f986 |
+else
|
|
|
f1f986 |
+ AC_MSG_RESULT(no)
|
|
|
f1f986 |
+fi
|
|
|
f1f986 |
+
|
|
|
f1f986 |
AC_ARG_WITH(docbook-xsl,
|
|
|
f1f986 |
AS_HELP_STRING([--with-docbook-xsl=DIR],
|
|
|
f1f986 |
[location of docbook 4.x xml stylesheets]),
|
|
|
f1f986 |
diff --git a/libqpdf/MD5-gnutls.cc b/libqpdf/MD5-gnutls.cc
|
|
|
f1f986 |
new file mode 100644
|
|
|
f1f986 |
index 0000000..5611b3e
|
|
|
f1f986 |
--- /dev/null
|
|
|
f1f986 |
+++ b/libqpdf/MD5-gnutls.cc
|
|
|
f1f986 |
@@ -0,0 +1,61 @@
|
|
|
f1f986 |
+#include <gnutls/crypto.h>
|
|
|
f1f986 |
+#include <qpdf/MD5.hh>
|
|
|
f1f986 |
+#include <qpdf/QUtil.hh>
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+// MD5 initialization. Begins an MD5 operation, writing a new context.
|
|
|
f1f986 |
+void MD5::init()
|
|
|
f1f986 |
+{
|
|
|
f1f986 |
+ int ret;
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+ ret = gnutls_hash_init(&ctx, GNUTLS_DIG_MD5);
|
|
|
f1f986 |
+ if (ret < 0) {
|
|
|
f1f986 |
+ QUtil::throw_system_error(
|
|
|
f1f986 |
+ std::string("GNU TLS: MD5 error:") + std::string(gnutls_strerror(ret)));
|
|
|
f1f986 |
+ ctx = nullptr;
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+ finalized = false;
|
|
|
f1f986 |
+ memset(digest_val, 0, sizeof(digest_val));
|
|
|
f1f986 |
+}
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+// MD5 block update operation. Continues an MD5 message-digest
|
|
|
f1f986 |
+// operation, processing another message block, and updating the
|
|
|
f1f986 |
+// context.
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+void MD5::update(unsigned char *input,
|
|
|
f1f986 |
+ unsigned int inputLen)
|
|
|
f1f986 |
+{
|
|
|
f1f986 |
+ if (ctx != nullptr && input != nullptr)
|
|
|
f1f986 |
+ gnutls_hash(ctx, input, inputLen);
|
|
|
f1f986 |
+}
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+// MD5 finalization. Ends an MD5 message-digest operation, writing the
|
|
|
f1f986 |
+// the message digest and zeroizing the context.
|
|
|
f1f986 |
+void MD5::final()
|
|
|
f1f986 |
+{
|
|
|
f1f986 |
+ if (finalized)
|
|
|
f1f986 |
+ return;
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+ if (ctx != nullptr)
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ gnutls_hash_deinit(ctx, digest_val);
|
|
|
f1f986 |
+ ctx = nullptr;
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+ finalized = true;
|
|
|
f1f986 |
+}
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+// MD5 basic transformation. Transforms state based on block.
|
|
|
f1f986 |
+void MD5::transform(UINT4 state[4], unsigned char block[64])
|
|
|
f1f986 |
+{}
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+// Encodes input (UINT4) into output (unsigned char). Assumes len is a
|
|
|
f1f986 |
+// multiple of 4.
|
|
|
f1f986 |
+void MD5::encode(unsigned char *output, UINT4 *input, unsigned int len)
|
|
|
f1f986 |
+{}
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+// Decodes input (unsigned char) into output (UINT4). Assumes len is a
|
|
|
f1f986 |
+// multiple of 4.
|
|
|
f1f986 |
+void MD5::decode(UINT4 *output, unsigned char *input, unsigned int len)
|
|
|
f1f986 |
+{}
|
|
|
f1f986 |
diff --git a/libqpdf/MD5.cc b/libqpdf/MD5.cc
|
|
|
f1f986 |
index 0504e2d..19dce79 100644
|
|
|
f1f986 |
--- a/libqpdf/MD5.cc
|
|
|
f1f986 |
+++ b/libqpdf/MD5.cc
|
|
|
f1f986 |
@@ -36,6 +36,10 @@
|
|
|
f1f986 |
#include <string.h>
|
|
|
f1f986 |
#include <errno.h>
|
|
|
f1f986 |
|
|
|
f1f986 |
+#ifdef HAVE_GNUTLS
|
|
|
f1f986 |
+# include "MD5-gnutls.cc"
|
|
|
f1f986 |
+#else
|
|
|
f1f986 |
+
|
|
|
f1f986 |
int const S11 = 7;
|
|
|
f1f986 |
int const S12 = 12;
|
|
|
f1f986 |
int const S13 = 17;
|
|
|
f1f986 |
@@ -294,6 +298,8 @@ void MD5::decode(UINT4 *output, unsigned char *input, unsigned int len)
|
|
|
f1f986 |
(static_cast<UINT4>(input[j+3]) << 24);
|
|
|
f1f986 |
}
|
|
|
f1f986 |
|
|
|
f1f986 |
+#endif /* HAVE_GNUTLS */
|
|
|
f1f986 |
+
|
|
|
f1f986 |
// Public functions
|
|
|
f1f986 |
|
|
|
f1f986 |
MD5::MD5()
|
|
|
f1f986 |
diff --git a/libqpdf/Pl_AES_PDF-gnutls.cc b/libqpdf/Pl_AES_PDF-gnutls.cc
|
|
|
f1f986 |
new file mode 100644
|
|
|
f1f986 |
index 0000000..7704e6d
|
|
|
f1f986 |
--- /dev/null
|
|
|
f1f986 |
+++ b/libqpdf/Pl_AES_PDF-gnutls.cc
|
|
|
f1f986 |
@@ -0,0 +1,246 @@
|
|
|
f1f986 |
+#include <qpdf/Pl_AES_PDF.hh>
|
|
|
f1f986 |
+#include <gnutls/crypto.h>
|
|
|
f1f986 |
+#include <qpdf/rijndael-gnutls.h>
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+bool Pl_AES_PDF::use_static_iv = false;
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+Pl_AES_PDF::Pl_AES_PDF(char const* identifier, Pipeline* next,
|
|
|
f1f986 |
+ bool encrypt, unsigned char const* key,
|
|
|
f1f986 |
+ unsigned int key_bytes) :
|
|
|
f1f986 |
+ Pipeline(identifier, next),
|
|
|
f1f986 |
+ encrypt(encrypt),
|
|
|
f1f986 |
+ cbc_mode(true),
|
|
|
f1f986 |
+ first(true),
|
|
|
f1f986 |
+ offset(0),
|
|
|
f1f986 |
+ nrounds(0),
|
|
|
f1f986 |
+ use_zero_iv(false),
|
|
|
f1f986 |
+ use_specified_iv(false),
|
|
|
f1f986 |
+ disable_padding(false)
|
|
|
f1f986 |
+{
|
|
|
f1f986 |
+ unsigned int keybits = 8 * key_bytes;
|
|
|
f1f986 |
+ this->keylen = key_bytes;
|
|
|
f1f986 |
+ this->ctx = nullptr;
|
|
|
f1f986 |
+ assert(key_bytes == KEYLENGTH(keybits));
|
|
|
f1f986 |
+ this->key = new unsigned char[key_bytes];
|
|
|
f1f986 |
+ this->rk = new uint32_t[RKLENGTH(keybits)];
|
|
|
f1f986 |
+ unsigned int rk_bytes = RKLENGTH(keybits) * sizeof(uint32_t);
|
|
|
f1f986 |
+ std::memcpy(this->key, key, key_bytes);
|
|
|
f1f986 |
+ std::memset(this->rk, 0, rk_bytes);
|
|
|
f1f986 |
+ std::memset(this->inbuf, 0, this->buf_size);
|
|
|
f1f986 |
+ std::memset(this->outbuf, 0, this->buf_size);
|
|
|
f1f986 |
+ std::memset(this->cbc_block, 0, this->buf_size);
|
|
|
f1f986 |
+}
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+Pl_AES_PDF::~Pl_AES_PDF()
|
|
|
f1f986 |
+{
|
|
|
f1f986 |
+ delete [] this->key;
|
|
|
f1f986 |
+ delete [] this->rk;
|
|
|
f1f986 |
+}
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+void
|
|
|
f1f986 |
+Pl_AES_PDF::useZeroIV()
|
|
|
f1f986 |
+{
|
|
|
f1f986 |
+ this->use_zero_iv = true;
|
|
|
f1f986 |
+}
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+void
|
|
|
f1f986 |
+Pl_AES_PDF::disablePadding()
|
|
|
f1f986 |
+{
|
|
|
f1f986 |
+ this->disable_padding = true;
|
|
|
f1f986 |
+}
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+void
|
|
|
f1f986 |
+Pl_AES_PDF::setIV(unsigned char const* iv, size_t bytes)
|
|
|
f1f986 |
+{
|
|
|
f1f986 |
+ if (bytes != this->buf_size)
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ throw std::logic_error(
|
|
|
f1f986 |
+ "Pl_AES_PDF: specified initialization vector"
|
|
|
f1f986 |
+ " size in bytes must be " + QUtil::int_to_string(bytes));
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+ this->use_specified_iv = true;
|
|
|
f1f986 |
+ memcpy(this->specified_iv, iv, bytes);
|
|
|
f1f986 |
+}
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+void
|
|
|
f1f986 |
+Pl_AES_PDF::disableCBC()
|
|
|
f1f986 |
+{
|
|
|
f1f986 |
+ this->cbc_mode = false;
|
|
|
f1f986 |
+}
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+void
|
|
|
f1f986 |
+Pl_AES_PDF::useStaticIV()
|
|
|
f1f986 |
+{
|
|
|
f1f986 |
+ use_static_iv = true;
|
|
|
f1f986 |
+}
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+void
|
|
|
f1f986 |
+Pl_AES_PDF::write(unsigned char* data, size_t len)
|
|
|
f1f986 |
+{
|
|
|
f1f986 |
+ size_t bytes_left = len;
|
|
|
f1f986 |
+ unsigned char* p = data;
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+ while (bytes_left > 0)
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ if (this->offset == this->buf_size)
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ flush(false);
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+ size_t available = this->buf_size - this->offset;
|
|
|
f1f986 |
+ size_t bytes = (bytes_left < available ? bytes_left : available);
|
|
|
f1f986 |
+ bytes_left -= bytes;
|
|
|
f1f986 |
+ std::memcpy(this->inbuf + this->offset, p, bytes);
|
|
|
f1f986 |
+ this->offset += bytes;
|
|
|
f1f986 |
+ p += bytes;
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+}
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+void
|
|
|
f1f986 |
+Pl_AES_PDF::finish()
|
|
|
f1f986 |
+{
|
|
|
f1f986 |
+ if (this->encrypt)
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ if (this->offset == this->buf_size)
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ flush(false);
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+ if (! this->disable_padding)
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ // Pad as described in section 3.5.1 of version 1.7 of the PDF
|
|
|
f1f986 |
+ // specification, including providing an entire block of padding
|
|
|
f1f986 |
+ // if the input was a multiple of 16 bytes.
|
|
|
f1f986 |
+ unsigned char pad =
|
|
|
f1f986 |
+ static_cast<unsigned char>(this->buf_size - this->offset);
|
|
|
f1f986 |
+ memset(this->inbuf + this->offset, pad, pad);
|
|
|
f1f986 |
+ this->offset = this->buf_size;
|
|
|
f1f986 |
+ flush(false);
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+ else
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ if (this->offset != this->buf_size)
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ // This is never supposed to happen as the output is
|
|
|
f1f986 |
+ // always supposed to be padded. However, we have
|
|
|
f1f986 |
+ // encountered files for which the output is not a
|
|
|
f1f986 |
+ // multiple of the block size. In this case, pad with
|
|
|
f1f986 |
+ // zeroes and hope for the best.
|
|
|
f1f986 |
+ assert(this->buf_size > this->offset);
|
|
|
f1f986 |
+ std::memset(this->inbuf + this->offset, 0,
|
|
|
f1f986 |
+ this->buf_size - this->offset);
|
|
|
f1f986 |
+ this->offset = this->buf_size;
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+ flush(! this->disable_padding);
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+ if (this->cbc_mode)
|
|
|
f1f986 |
+ rijndaelFinish(this->ctx);
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+ getNext()->finish();
|
|
|
f1f986 |
+}
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+void
|
|
|
f1f986 |
+Pl_AES_PDF::initializeVector()
|
|
|
f1f986 |
+{
|
|
|
f1f986 |
+ if (use_zero_iv)
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ for (unsigned int i = 0; i < this->buf_size; ++i)
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ this->cbc_block[i] = 0;
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+ else if (use_specified_iv)
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ std::memcpy(this->cbc_block, this->specified_iv, this->buf_size);
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+ else if (use_static_iv)
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ for (unsigned int i = 0; i < this->buf_size; ++i)
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ this->cbc_block[i] = 14 * (1 + i);
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+ else
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ QUtil::initializeWithRandomBytes(this->cbc_block, this->buf_size);
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+}
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+void
|
|
|
f1f986 |
+Pl_AES_PDF::flush(bool strip_padding)
|
|
|
f1f986 |
+{
|
|
|
f1f986 |
+ assert(this->offset == this->buf_size);
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+ if (first)
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ first = false;
|
|
|
f1f986 |
+ if (this->cbc_mode)
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ if (encrypt)
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ // Set cbc_block to the initialization vector, and if
|
|
|
f1f986 |
+ // not zero, write it to the output stream.
|
|
|
f1f986 |
+ initializeVector();
|
|
|
f1f986 |
+ if (! (this->use_zero_iv || this->use_specified_iv))
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ getNext()->write(this->cbc_block, this->buf_size);
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+ else if (this->use_zero_iv || this->use_specified_iv)
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ // Initialize vector with zeroes; zero vector was not
|
|
|
f1f986 |
+ // written to the beginning of the input file.
|
|
|
f1f986 |
+ initializeVector();
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+ else
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ // Take the first block of input as the initialization
|
|
|
f1f986 |
+ // vector. There's nothing to write at this time.
|
|
|
f1f986 |
+ memcpy(this->cbc_block, this->inbuf, this->buf_size);
|
|
|
f1f986 |
+ this->offset = 0;
|
|
|
f1f986 |
+ rijndaelInit(&(this->ctx), this->key, this->keylen, this->cbc_block, this->buf_size);
|
|
|
f1f986 |
+ return;
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+ rijndaelInit(&(this->ctx), this->key, this->keylen, this->cbc_block, this->buf_size);
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+ if (this->encrypt)
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ if (this->cbc_mode)
|
|
|
f1f986 |
+ rijndaelCBCEncrypt(this->ctx, this->inbuf, this->outbuf, this->buf_size);
|
|
|
f1f986 |
+ else
|
|
|
f1f986 |
+ rijndaelECBEncrypt(this->key, this->keylen, this->cbc_block, this->inbuf, this->outbuf, this->buf_size);
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+ else
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ if (this->cbc_mode)
|
|
|
f1f986 |
+ rijndaelCBCDecrypt(this->ctx, this->inbuf, this->outbuf, this->buf_size);
|
|
|
f1f986 |
+ else
|
|
|
f1f986 |
+ rijndaelECBDecrypt(this->key, this->keylen, this->cbc_block, this->inbuf, this->outbuf, this->buf_size);
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+ unsigned int bytes = this->buf_size;
|
|
|
f1f986 |
+ if (strip_padding)
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ unsigned char last = this->outbuf[this->buf_size - 1];
|
|
|
f1f986 |
+ if (last <= this->buf_size)
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ bool strip = true;
|
|
|
f1f986 |
+ for (unsigned int i = 1; i <= last; ++i)
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ if (this->outbuf[this->buf_size - i] != last)
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ strip = false;
|
|
|
f1f986 |
+ break;
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+ if (strip)
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ bytes -= last;
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+ getNext()->write(this->outbuf, bytes);
|
|
|
f1f986 |
+ this->offset = 0;
|
|
|
f1f986 |
+}
|
|
|
f1f986 |
diff --git a/libqpdf/Pl_AES_PDF.cc b/libqpdf/Pl_AES_PDF.cc
|
|
|
f1f986 |
index 5c493cb..ac8bde4 100644
|
|
|
f1f986 |
--- a/libqpdf/Pl_AES_PDF.cc
|
|
|
f1f986 |
+++ b/libqpdf/Pl_AES_PDF.cc
|
|
|
f1f986 |
@@ -3,10 +3,15 @@
|
|
|
f1f986 |
#include <cstring>
|
|
|
f1f986 |
#include <assert.h>
|
|
|
f1f986 |
#include <stdexcept>
|
|
|
f1f986 |
-#include <qpdf/rijndael.h>
|
|
|
f1f986 |
+
|
|
|
f1f986 |
#include <string>
|
|
|
f1f986 |
#include <stdlib.h>
|
|
|
f1f986 |
|
|
|
f1f986 |
+#ifdef HAVE_GNUTLS
|
|
|
f1f986 |
+# include "Pl_AES_PDF-gnutls.cc"
|
|
|
f1f986 |
+#else
|
|
|
f1f986 |
+# include <qpdf/rijndael.h>
|
|
|
f1f986 |
+
|
|
|
f1f986 |
bool Pl_AES_PDF::use_static_iv = false;
|
|
|
f1f986 |
|
|
|
f1f986 |
Pl_AES_PDF::Pl_AES_PDF(char const* identifier, Pipeline* next,
|
|
|
f1f986 |
@@ -263,3 +268,4 @@ Pl_AES_PDF::flush(bool strip_padding)
|
|
|
f1f986 |
getNext()->write(this->outbuf, bytes);
|
|
|
f1f986 |
this->offset = 0;
|
|
|
f1f986 |
}
|
|
|
f1f986 |
+#endif
|
|
|
f1f986 |
diff --git a/libqpdf/Pl_SHA2.cc b/libqpdf/Pl_SHA2.cc
|
|
|
f1f986 |
index 17eff7e..9156451 100644
|
|
|
f1f986 |
--- a/libqpdf/Pl_SHA2.cc
|
|
|
f1f986 |
+++ b/libqpdf/Pl_SHA2.cc
|
|
|
f1f986 |
@@ -13,6 +13,12 @@ Pl_SHA2::Pl_SHA2(int bits, Pipeline* next) :
|
|
|
f1f986 |
{
|
|
|
f1f986 |
resetBits(bits);
|
|
|
f1f986 |
}
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+#ifdef HAVE_GNUTLS
|
|
|
f1f986 |
+ this->ctx256 = nullptr;
|
|
|
f1f986 |
+ this->ctx384 = nullptr;
|
|
|
f1f986 |
+ this->ctx512 = nullptr;
|
|
|
f1f986 |
+#endif
|
|
|
f1f986 |
}
|
|
|
f1f986 |
|
|
|
f1f986 |
Pl_SHA2::~Pl_SHA2()
|
|
|
f1f986 |
diff --git a/libqpdf/RC4-gnutls.cc b/libqpdf/RC4-gnutls.cc
|
|
|
f1f986 |
new file mode 100644
|
|
|
f1f986 |
index 0000000..093a5b9
|
|
|
f1f986 |
--- /dev/null
|
|
|
f1f986 |
+++ b/libqpdf/RC4-gnutls.cc
|
|
|
f1f986 |
@@ -0,0 +1,51 @@
|
|
|
f1f986 |
+#include <qpdf/RC4.hh>
|
|
|
f1f986 |
+#include <qpdf/QUtil.hh>
|
|
|
f1f986 |
+#include <gnutls/crypto.h>
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+RC4::RC4(unsigned char const* key_data, int key_len)
|
|
|
f1f986 |
+{
|
|
|
f1f986 |
+ if (key_len == -1)
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ key_len = strlen(reinterpret_cast<char const*>(key_data));
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+ int ret;
|
|
|
f1f986 |
+ gnutls_cipher_algorithm_t alg = GNUTLS_CIPHER_ARCFOUR_128;
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+ this->key.data = const_cast<unsigned char*>(key_data);
|
|
|
f1f986 |
+ this->key.size = key_len;
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+ ret = gnutls_cipher_init(&(this->ctx),
|
|
|
f1f986 |
+ alg,
|
|
|
f1f986 |
+ &(this->key),
|
|
|
f1f986 |
+ NULL);
|
|
|
f1f986 |
+ if (ret < 0)
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ QUtil::throw_system_error(
|
|
|
f1f986 |
+ std::string("GNU TLS: RC4 error: ") + std::string(gnutls_strerror(ret)));
|
|
|
f1f986 |
+ this->ctx = nullptr;
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+}
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+RC4::~RC4()
|
|
|
f1f986 |
+{
|
|
|
f1f986 |
+ if (this->ctx != nullptr)
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ gnutls_cipher_deinit(this->ctx);
|
|
|
f1f986 |
+ this->ctx = nullptr;
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+}
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+void
|
|
|
f1f986 |
+RC4::process(unsigned char *in_data, int len, unsigned char* out_data)
|
|
|
f1f986 |
+{
|
|
|
f1f986 |
+ if (out_data == 0)
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ // Convert in place
|
|
|
f1f986 |
+ out_data = in_data;
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+ if (this->ctx != nullptr && in_data != nullptr)
|
|
|
f1f986 |
+ gnutls_cipher_encrypt2(this->ctx, in_data, len, out_data, len);
|
|
|
f1f986 |
+}
|
|
|
f1f986 |
diff --git a/libqpdf/RC4.cc b/libqpdf/RC4.cc
|
|
|
f1f986 |
index 7639a36..c1288be 100644
|
|
|
f1f986 |
--- a/libqpdf/RC4.cc
|
|
|
f1f986 |
+++ b/libqpdf/RC4.cc
|
|
|
f1f986 |
@@ -2,6 +2,10 @@
|
|
|
f1f986 |
|
|
|
f1f986 |
#include <string.h>
|
|
|
f1f986 |
|
|
|
f1f986 |
+#ifdef HAVE_GNUTLS
|
|
|
f1f986 |
+# include "RC4-gnutls.cc"
|
|
|
f1f986 |
+#else
|
|
|
f1f986 |
+
|
|
|
f1f986 |
static void swap_byte(unsigned char &a, unsigned char &b)
|
|
|
f1f986 |
{
|
|
|
f1f986 |
unsigned char t;
|
|
|
f1f986 |
@@ -53,3 +57,4 @@ RC4::process(unsigned char *in_data, int len, unsigned char* out_data)
|
|
|
f1f986 |
out_data[i] = in_data[i] ^ key.state[xor_index];
|
|
|
f1f986 |
}
|
|
|
f1f986 |
}
|
|
|
f1f986 |
+#endif
|
|
|
f1f986 |
diff --git a/libqpdf/SecureRandomDataProvider.cc b/libqpdf/SecureRandomDataProvider.cc
|
|
|
f1f986 |
index fe9f1d4..d72269e 100644
|
|
|
f1f986 |
--- a/libqpdf/SecureRandomDataProvider.cc
|
|
|
f1f986 |
+++ b/libqpdf/SecureRandomDataProvider.cc
|
|
|
f1f986 |
@@ -11,6 +11,10 @@
|
|
|
f1f986 |
# endif
|
|
|
f1f986 |
#endif
|
|
|
f1f986 |
|
|
|
f1f986 |
+#ifdef HAVE_GNUTLS
|
|
|
f1f986 |
+# include <gnutls/crypto.h>
|
|
|
f1f986 |
+#endif
|
|
|
f1f986 |
+
|
|
|
f1f986 |
SecureRandomDataProvider::SecureRandomDataProvider()
|
|
|
f1f986 |
{
|
|
|
f1f986 |
}
|
|
|
f1f986 |
@@ -89,7 +93,19 @@ class WindowsCryptProvider
|
|
|
f1f986 |
void
|
|
|
f1f986 |
SecureRandomDataProvider::provideRandomData(unsigned char* data, size_t len)
|
|
|
f1f986 |
{
|
|
|
f1f986 |
-#if defined(_WIN32)
|
|
|
f1f986 |
+#if defined(HAVE_GNUTLS)
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+ int ret = 0;
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+ ret = gnutls_rnd(GNUTLS_RND_NONCE, data, len);
|
|
|
f1f986 |
+ if (ret < 0)
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ throw std::runtime_error(
|
|
|
f1f986 |
+ "GNU TLS: unable to generate secure random data " +
|
|
|
f1f986 |
+ std::string(gnutls_strerror(ret)));
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+#elif defined(_WIN32)
|
|
|
f1f986 |
|
|
|
f1f986 |
// Optimization: make the WindowsCryptProvider static as long as
|
|
|
f1f986 |
// it can be done in a thread-safe fashion.
|
|
|
f1f986 |
diff --git a/libqpdf/qpdf/MD5.hh b/libqpdf/qpdf/MD5.hh
|
|
|
f1f986 |
index 4cfe027..bb9f756 100644
|
|
|
f1f986 |
--- a/libqpdf/qpdf/MD5.hh
|
|
|
f1f986 |
+++ b/libqpdf/qpdf/MD5.hh
|
|
|
f1f986 |
@@ -11,6 +11,10 @@
|
|
|
f1f986 |
#endif
|
|
|
f1f986 |
#include <string>
|
|
|
f1f986 |
|
|
|
f1f986 |
+#ifdef HAVE_GNUTLS
|
|
|
f1f986 |
+# include <gnutls/crypto.h>
|
|
|
f1f986 |
+#endif
|
|
|
f1f986 |
+
|
|
|
f1f986 |
class MD5
|
|
|
f1f986 |
{
|
|
|
f1f986 |
public:
|
|
|
f1f986 |
@@ -87,6 +91,9 @@ class MD5
|
|
|
f1f986 |
|
|
|
f1f986 |
bool finalized;
|
|
|
f1f986 |
Digest digest_val;
|
|
|
f1f986 |
+#ifdef HAVE_GNUTLS
|
|
|
f1f986 |
+ gnutls_hash_hd_t ctx;
|
|
|
f1f986 |
+#endif
|
|
|
f1f986 |
};
|
|
|
f1f986 |
|
|
|
f1f986 |
#endif // __MD5_HH__
|
|
|
f1f986 |
diff --git a/libqpdf/qpdf/Pl_AES_PDF.hh b/libqpdf/qpdf/Pl_AES_PDF.hh
|
|
|
f1f986 |
index 9aa73ad..8059e7d 100644
|
|
|
f1f986 |
--- a/libqpdf/qpdf/Pl_AES_PDF.hh
|
|
|
f1f986 |
+++ b/libqpdf/qpdf/Pl_AES_PDF.hh
|
|
|
f1f986 |
@@ -7,6 +7,10 @@
|
|
|
f1f986 |
# include <stdint.h>
|
|
|
f1f986 |
#endif
|
|
|
f1f986 |
|
|
|
f1f986 |
+#ifdef HAVE_GNUTLS
|
|
|
f1f986 |
+# include <gnutls/crypto.h>
|
|
|
f1f986 |
+#endif
|
|
|
f1f986 |
+
|
|
|
f1f986 |
// This pipeline implements AES-128 and AES-256 with CBC and block
|
|
|
f1f986 |
// padding as specified in the PDF specification.
|
|
|
f1f986 |
|
|
|
f1f986 |
@@ -64,6 +68,11 @@ class Pl_AES_PDF: public Pipeline
|
|
|
f1f986 |
bool use_zero_iv;
|
|
|
f1f986 |
bool use_specified_iv;
|
|
|
f1f986 |
bool disable_padding;
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+#ifdef HAVE_GNUTLS
|
|
|
f1f986 |
+ gnutls_cipher_hd_t ctx;
|
|
|
f1f986 |
+ unsigned int keylen;
|
|
|
f1f986 |
+#endif
|
|
|
f1f986 |
};
|
|
|
f1f986 |
|
|
|
f1f986 |
#endif // __PL_AES_PDF_HH__
|
|
|
f1f986 |
diff --git a/libqpdf/qpdf/RC4.hh b/libqpdf/qpdf/RC4.hh
|
|
|
f1f986 |
index c26f3d0..1421a08 100644
|
|
|
f1f986 |
--- a/libqpdf/qpdf/RC4.hh
|
|
|
f1f986 |
+++ b/libqpdf/qpdf/RC4.hh
|
|
|
f1f986 |
@@ -1,6 +1,12 @@
|
|
|
f1f986 |
#ifndef __RC4_HH__
|
|
|
f1f986 |
#define __RC4_HH__
|
|
|
f1f986 |
|
|
|
f1f986 |
+#include <qpdf/qpdf-config.h>
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+#ifdef HAVE_GNUTLS
|
|
|
f1f986 |
+# include <gnutls/crypto.h>
|
|
|
f1f986 |
+#endif
|
|
|
f1f986 |
+
|
|
|
f1f986 |
class RC4
|
|
|
f1f986 |
{
|
|
|
f1f986 |
public:
|
|
|
f1f986 |
@@ -10,7 +16,15 @@ class RC4
|
|
|
f1f986 |
// out_data = 0 means to encrypt/decrypt in place
|
|
|
f1f986 |
void process(unsigned char* in_data, int len, unsigned char* out_data = 0);
|
|
|
f1f986 |
|
|
|
f1f986 |
+#ifdef HAVE_GNUTLS
|
|
|
f1f986 |
+ ~RC4();
|
|
|
f1f986 |
+#endif
|
|
|
f1f986 |
+
|
|
|
f1f986 |
private:
|
|
|
f1f986 |
+#ifdef HAVE_GNUTLS
|
|
|
f1f986 |
+ gnutls_cipher_hd_t ctx;
|
|
|
f1f986 |
+ gnutls_datum_t key;
|
|
|
f1f986 |
+#else
|
|
|
f1f986 |
class RC4Key
|
|
|
f1f986 |
{
|
|
|
f1f986 |
public:
|
|
|
f1f986 |
@@ -20,6 +34,7 @@ class RC4
|
|
|
f1f986 |
};
|
|
|
f1f986 |
|
|
|
f1f986 |
RC4Key key;
|
|
|
f1f986 |
+#endif
|
|
|
f1f986 |
};
|
|
|
f1f986 |
|
|
|
f1f986 |
#endif // __RC4_HH__
|
|
|
f1f986 |
diff --git a/libqpdf/qpdf/rijndael-gnutls.h b/libqpdf/qpdf/rijndael-gnutls.h
|
|
|
f1f986 |
new file mode 100644
|
|
|
f1f986 |
index 0000000..a3e7ff0
|
|
|
f1f986 |
--- /dev/null
|
|
|
f1f986 |
+++ b/libqpdf/qpdf/rijndael-gnutls.h
|
|
|
f1f986 |
@@ -0,0 +1,32 @@
|
|
|
f1f986 |
+#ifdef HAVE_INTTYPES_H
|
|
|
f1f986 |
+# include <inttypes.h>
|
|
|
f1f986 |
+#endif
|
|
|
f1f986 |
+#ifdef HAVE_STDINT_H
|
|
|
f1f986 |
+# include <stdint.h>
|
|
|
f1f986 |
+#endif
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+#include <gnutls/crypto.h>
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+void rijndaelInit(gnutls_cipher_hd_t * context, unsigned char * key,
|
|
|
f1f986 |
+ unsigned int keylen, unsigned char cbc_block[16], unsigned int buf_size);
|
|
|
f1f986 |
+int rijndaelSetupEncrypt(uint32_t *rk, const unsigned char *key,
|
|
|
f1f986 |
+ int keybits);
|
|
|
f1f986 |
+int rijndaelSetupDecrypt(uint32_t *rk, const unsigned char *key,
|
|
|
f1f986 |
+ int keybits);
|
|
|
f1f986 |
+void rijndaelCBCEncrypt(gnutls_cipher_hd_t context,
|
|
|
f1f986 |
+ const unsigned char plaintext[16], unsigned char ciphertext[16],
|
|
|
f1f986 |
+ unsigned int buf_size);
|
|
|
f1f986 |
+void rijndaelCBCDecrypt(gnutls_cipher_hd_t context,
|
|
|
f1f986 |
+ const unsigned char ciphertext[16], unsigned char plaintext[16],
|
|
|
f1f986 |
+ unsigned int buf_size);
|
|
|
f1f986 |
+void rijndaelECBEncrypt(unsigned char * key, unsigned int keylen,
|
|
|
f1f986 |
+ unsigned char cbc_block[16], const unsigned char plaintext[16],
|
|
|
f1f986 |
+ unsigned char ciphertext[16], unsigned int buf_size);
|
|
|
f1f986 |
+void rijndaelECBDecrypt(unsigned char * key, unsigned int keylen,
|
|
|
f1f986 |
+ unsigned char cbc_block[16], const unsigned char ciphertext[16],
|
|
|
f1f986 |
+ unsigned char plaintext[16], unsigned int buf_size);
|
|
|
f1f986 |
+void rijndaelFinish(gnutls_cipher_hd_t context);
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+#define KEYLENGTH(keybits) ((keybits)/8)
|
|
|
f1f986 |
+#define RKLENGTH(keybits) ((keybits)/8+28)
|
|
|
f1f986 |
+#define NROUNDS(keybits) ((keybits)/32+6)
|
|
|
f1f986 |
diff --git a/libqpdf/qpdf/rijndael.h b/libqpdf/qpdf/rijndael.h
|
|
|
f1f986 |
index a9cd71d..9698a8b 100644
|
|
|
f1f986 |
--- a/libqpdf/qpdf/rijndael.h
|
|
|
f1f986 |
+++ b/libqpdf/qpdf/rijndael.h
|
|
|
f1f986 |
@@ -9,6 +9,10 @@
|
|
|
f1f986 |
# include <stdint.h>
|
|
|
f1f986 |
#endif
|
|
|
f1f986 |
|
|
|
f1f986 |
+#ifdef HAVE_GNUTLS
|
|
|
f1f986 |
+# include "qpdf/rijndael-gnutls.h"
|
|
|
f1f986 |
+#else
|
|
|
f1f986 |
+
|
|
|
f1f986 |
int rijndaelSetupEncrypt(uint32_t *rk, const unsigned char *key,
|
|
|
f1f986 |
int keybits);
|
|
|
f1f986 |
int rijndaelSetupDecrypt(uint32_t *rk, const unsigned char *key,
|
|
|
f1f986 |
@@ -22,4 +26,6 @@ void rijndaelDecrypt(const uint32_t *rk, int nrounds,
|
|
|
f1f986 |
#define RKLENGTH(keybits) ((keybits)/8+28)
|
|
|
f1f986 |
#define NROUNDS(keybits) ((keybits)/32+6)
|
|
|
f1f986 |
|
|
|
f1f986 |
+#endif /* HAVE_GNUTLS */
|
|
|
f1f986 |
+
|
|
|
f1f986 |
#endif
|
|
|
f1f986 |
diff --git a/libqpdf/rijndael-gnutls.cc b/libqpdf/rijndael-gnutls.cc
|
|
|
f1f986 |
new file mode 100644
|
|
|
f1f986 |
index 0000000..dd3fdb2
|
|
|
f1f986 |
--- /dev/null
|
|
|
f1f986 |
+++ b/libqpdf/rijndael-gnutls.cc
|
|
|
f1f986 |
@@ -0,0 +1,116 @@
|
|
|
f1f986 |
+#include <cstring>
|
|
|
f1f986 |
+#include <gnutls/crypto.h>
|
|
|
f1f986 |
+#include <qpdf/QUtil.hh>
|
|
|
f1f986 |
+#include <qpdf/rijndael-gnutls.h>
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+typedef uint32_t u32;
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+/**
|
|
|
f1f986 |
+ * Init cryptographic context
|
|
|
f1f986 |
+ */
|
|
|
f1f986 |
+void rijndaelInit(gnutls_cipher_hd_t * ctx, unsigned char * key,
|
|
|
f1f986 |
+ unsigned int keylen, unsigned char cbc_block[16],
|
|
|
f1f986 |
+ unsigned int buf_size)
|
|
|
f1f986 |
+{
|
|
|
f1f986 |
+ int ret;
|
|
|
f1f986 |
+ gnutls_cipher_algorithm_t alg;
|
|
|
f1f986 |
+ gnutls_datum_t cipher_key;
|
|
|
f1f986 |
+ gnutls_datum_t iv;
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+ cipher_key.data = key;
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+ switch(keylen) {
|
|
|
f1f986 |
+ case 16:
|
|
|
f1f986 |
+ alg = GNUTLS_CIPHER_AES_128_CBC;
|
|
|
f1f986 |
+ break;
|
|
|
f1f986 |
+ case 32:
|
|
|
f1f986 |
+ alg = GNUTLS_CIPHER_AES_256_CBC;
|
|
|
f1f986 |
+ break;
|
|
|
f1f986 |
+ case 24:
|
|
|
f1f986 |
+ alg = GNUTLS_CIPHER_AES_192_CBC;
|
|
|
f1f986 |
+ break;
|
|
|
f1f986 |
+ default:
|
|
|
f1f986 |
+ alg = GNUTLS_CIPHER_AES_128_CBC;
|
|
|
f1f986 |
+ break;
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+ cipher_key.size = gnutls_cipher_get_key_size(alg);
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+ iv.data = cbc_block;
|
|
|
f1f986 |
+ iv.size = buf_size;
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+ ret = gnutls_cipher_init(ctx, alg, &cipher_key, &iv;;
|
|
|
f1f986 |
+ if (ret < 0)
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ QUtil::throw_system_error(
|
|
|
f1f986 |
+ std::string("GNU TLS: AES error: ") + std::string(gnutls_strerror(ret)));
|
|
|
f1f986 |
+ ctx = NULL;
|
|
|
f1f986 |
+ return;
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+}
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+/**
|
|
|
f1f986 |
+ * Encrypt string by AES CBC by GNU TLS.
|
|
|
f1f986 |
+ */
|
|
|
f1f986 |
+void rijndaelCBCEncrypt(gnutls_cipher_hd_t ctx,
|
|
|
f1f986 |
+ const unsigned char plaintext[16], unsigned char ciphertext[16],
|
|
|
f1f986 |
+ unsigned int buf_size)
|
|
|
f1f986 |
+{
|
|
|
f1f986 |
+ if (ctx != nullptr)
|
|
|
f1f986 |
+ gnutls_cipher_encrypt2(ctx, plaintext, buf_size, ciphertext, buf_size);
|
|
|
f1f986 |
+}
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+/**
|
|
|
f1f986 |
+ * Decrypt string by AES CBC by GNU TLS.
|
|
|
f1f986 |
+ */
|
|
|
f1f986 |
+void rijndaelCBCDecrypt(gnutls_cipher_hd_t ctx,
|
|
|
f1f986 |
+ const unsigned char ciphertext[16], unsigned char plaintext[16],
|
|
|
f1f986 |
+ unsigned int buf_size)
|
|
|
f1f986 |
+{
|
|
|
f1f986 |
+ if (ctx != nullptr)
|
|
|
f1f986 |
+ gnutls_cipher_decrypt2(ctx, ciphertext, buf_size, plaintext, buf_size);
|
|
|
f1f986 |
+}
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+/**
|
|
|
f1f986 |
+ * Encrypt string by AES ECB by GNU TLS.
|
|
|
f1f986 |
+ */
|
|
|
f1f986 |
+void rijndaelECBEncrypt(unsigned char * key, unsigned int keylen,
|
|
|
f1f986 |
+ unsigned char cbc_block[16], const unsigned char ciphertext[16],
|
|
|
f1f986 |
+ unsigned char plaintext[16], unsigned int buf_size)
|
|
|
f1f986 |
+{
|
|
|
f1f986 |
+ gnutls_cipher_hd_t ctx;
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+ rijndaelInit(&ctx, key, keylen, cbc_block, buf_size);
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+ rijndaelCBCEncrypt(ctx, ciphertext, plaintext, buf_size);
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+ rijndaelFinish(ctx);
|
|
|
f1f986 |
+}
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+/**
|
|
|
f1f986 |
+ * Decrypt string by AES ECB by GNU TLS.
|
|
|
f1f986 |
+ */
|
|
|
f1f986 |
+void rijndaelECBDecrypt(unsigned char * key, unsigned int keylen,
|
|
|
f1f986 |
+ unsigned char cbc_block[16], const unsigned char ciphertext[16],
|
|
|
f1f986 |
+ unsigned char plaintext[16], unsigned int buf_size)
|
|
|
f1f986 |
+{
|
|
|
f1f986 |
+ gnutls_cipher_hd_t ctx;
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+ rijndaelInit(&ctx, key, keylen, cbc_block, buf_size);
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+ rijndaelCBCDecrypt(ctx, ciphertext, plaintext, buf_size);
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+ rijndaelFinish(ctx);
|
|
|
f1f986 |
+}
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+/**
|
|
|
f1f986 |
+ * Finish cryptography context
|
|
|
f1f986 |
+ */
|
|
|
f1f986 |
+void rijndaelFinish(gnutls_cipher_hd_t ctx)
|
|
|
f1f986 |
+{
|
|
|
f1f986 |
+ if (ctx != nullptr)
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ gnutls_cipher_deinit(ctx);
|
|
|
f1f986 |
+ ctx = nullptr;
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+}
|
|
|
f1f986 |
diff --git a/libqpdf/rijndael.cc b/libqpdf/rijndael.cc
|
|
|
f1f986 |
index 7f711df..117c1a1 100644
|
|
|
f1f986 |
--- a/libqpdf/rijndael.cc
|
|
|
f1f986 |
+++ b/libqpdf/rijndael.cc
|
|
|
f1f986 |
@@ -2,6 +2,10 @@
|
|
|
f1f986 |
|
|
|
f1f986 |
#include "qpdf/rijndael.h"
|
|
|
f1f986 |
|
|
|
f1f986 |
+#ifdef HAVE_GNUTLS
|
|
|
f1f986 |
+# include "rijndael-gnutls.cc"
|
|
|
f1f986 |
+#else
|
|
|
f1f986 |
+
|
|
|
f1f986 |
typedef uint32_t u32;
|
|
|
f1f986 |
typedef unsigned char u8;
|
|
|
f1f986 |
|
|
|
f1f986 |
@@ -1206,3 +1210,4 @@ void rijndaelDecrypt(const u32 *rk, int nrounds, const u8 ciphertext[16],
|
|
|
f1f986 |
rk[3];
|
|
|
f1f986 |
PUTU32(plaintext + 12, s3);
|
|
|
f1f986 |
}
|
|
|
f1f986 |
+#endif
|
|
|
f1f986 |
diff --git a/libqpdf/sha2-gnutls.c b/libqpdf/sha2-gnutls.c
|
|
|
f1f986 |
new file mode 100644
|
|
|
f1f986 |
index 0000000..29155d5
|
|
|
f1f986 |
--- /dev/null
|
|
|
f1f986 |
+++ b/libqpdf/sha2-gnutls.c
|
|
|
f1f986 |
@@ -0,0 +1,41 @@
|
|
|
f1f986 |
+#include <gnutls/crypto.h>
|
|
|
f1f986 |
+#include <stdio.h>
|
|
|
f1f986 |
+#include "sph/sph_sha2_gnutls.h"
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+/* see sph_sha2.h */
|
|
|
f1f986 |
+void
|
|
|
f1f986 |
+sph_sha256_init(void * cc)
|
|
|
f1f986 |
+{
|
|
|
f1f986 |
+ int ret;
|
|
|
f1f986 |
+ gnutls_hash_hd_t * ctx = (gnutls_hash_hd_t*) cc;
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+ ret = gnutls_hash_init(ctx, GNUTLS_DIG_SHA256);
|
|
|
f1f986 |
+ if (ret < 0)
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ fprintf(stderr, "GNU TLS: SHA256 error : %s\n", gnutls_strerror(ret));
|
|
|
f1f986 |
+ cc = NULL;
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+}
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+/* see sph_sha2.h */
|
|
|
f1f986 |
+void
|
|
|
f1f986 |
+sph_sha256_close(void * cc, void *dst)
|
|
|
f1f986 |
+{
|
|
|
f1f986 |
+ gnutls_hash_hd_t * ctx = (gnutls_hash_hd_t*) cc;
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+ if (ctx != NULL)
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ gnutls_hash_deinit(*(ctx), dst);
|
|
|
f1f986 |
+ cc = NULL;
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+}
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+/* see sph_sha2.h */
|
|
|
f1f986 |
+void sph_sha256(void * cc, const void * data, size_t len)
|
|
|
f1f986 |
+{
|
|
|
f1f986 |
+ gnutls_hash_hd_t * ctx = (gnutls_hash_hd_t*) cc;
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+ if (ctx != NULL && data != NULL)
|
|
|
f1f986 |
+ gnutls_hash(*(ctx), data, len);
|
|
|
f1f986 |
+}
|
|
|
f1f986 |
diff --git a/libqpdf/sha2.c b/libqpdf/sha2.c
|
|
|
f1f986 |
index 45fdd7e..e240f9b 100644
|
|
|
f1f986 |
--- a/libqpdf/sha2.c
|
|
|
f1f986 |
+++ b/libqpdf/sha2.c
|
|
|
f1f986 |
@@ -35,6 +35,10 @@
|
|
|
f1f986 |
|
|
|
f1f986 |
#include "sph/sph_sha2.h"
|
|
|
f1f986 |
|
|
|
f1f986 |
+#ifdef HAVE_GNUTLS
|
|
|
f1f986 |
+# include "sha2-gnutls.c"
|
|
|
f1f986 |
+#else
|
|
|
f1f986 |
+
|
|
|
f1f986 |
#if SPH_SMALL_FOOTPRINT && !defined SPH_SMALL_FOOTPRINT_SHA2
|
|
|
f1f986 |
#define SPH_SMALL_FOOTPRINT_SHA2 1
|
|
|
f1f986 |
#endif
|
|
|
f1f986 |
@@ -688,3 +692,5 @@ sph_sha224_comp(const sph_u32 msg[16], sph_u32 val[8])
|
|
|
f1f986 |
SHA2_ROUND_BODY(SHA2_IN, val);
|
|
|
f1f986 |
#undef SHA2_IN
|
|
|
f1f986 |
}
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+#endif /* HAVE_GNUTLS */
|
|
|
f1f986 |
diff --git a/libqpdf/sha2big-gnutls.c b/libqpdf/sha2big-gnutls.c
|
|
|
f1f986 |
new file mode 100644
|
|
|
f1f986 |
index 0000000..494e2b4
|
|
|
f1f986 |
--- /dev/null
|
|
|
f1f986 |
+++ b/libqpdf/sha2big-gnutls.c
|
|
|
f1f986 |
@@ -0,0 +1,80 @@
|
|
|
f1f986 |
+#include <gnutls/crypto.h>
|
|
|
f1f986 |
+#include <stdio.h>
|
|
|
f1f986 |
+#include "sph/sph_sha2_gnutls.h"
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+/* see sph_sha3.h */
|
|
|
f1f986 |
+void
|
|
|
f1f986 |
+sph_sha384_init(void * cc)
|
|
|
f1f986 |
+{
|
|
|
f1f986 |
+ int ret;
|
|
|
f1f986 |
+ gnutls_hash_hd_t * ctx = (gnutls_hash_hd_t*) cc;
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+ ret = gnutls_hash_init(ctx, GNUTLS_DIG_SHA384);
|
|
|
f1f986 |
+ if (ret < 0)
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ fprintf(stderr, "GNU TLS: SHA384 error: %s\n", gnutls_strerror(ret));
|
|
|
f1f986 |
+ cc = NULL;
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+}
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+/* see sph_sha3.h */
|
|
|
f1f986 |
+void
|
|
|
f1f986 |
+sph_sha384_close(void * cc, void *dst)
|
|
|
f1f986 |
+{
|
|
|
f1f986 |
+ gnutls_hash_hd_t * ctx = (gnutls_hash_hd_t*) cc;
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+ if (ctx != NULL && dst != NULL)
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ gnutls_hash_deinit(*(ctx), dst);
|
|
|
f1f986 |
+ cc = NULL;
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+}
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+/* see sph_sha3.h */
|
|
|
f1f986 |
+void
|
|
|
f1f986 |
+sph_sha384(void * cc, const void * data, size_t len)
|
|
|
f1f986 |
+{
|
|
|
f1f986 |
+ gnutls_hash_hd_t * ctx = (gnutls_hash_hd_t*) cc;
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+ if (ctx != NULL && data != NULL)
|
|
|
f1f986 |
+ gnutls_hash(*(ctx), data, len);
|
|
|
f1f986 |
+}
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+/* see sph_sha3.h */
|
|
|
f1f986 |
+void
|
|
|
f1f986 |
+sph_sha512_init(void * cc)
|
|
|
f1f986 |
+{
|
|
|
f1f986 |
+ int ret;
|
|
|
f1f986 |
+ gnutls_hash_hd_t * ctx = (gnutls_hash_hd_t*) cc;
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+ ret = gnutls_hash_init(ctx, GNUTLS_DIG_SHA512);
|
|
|
f1f986 |
+ if (ret < 0)
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ fprintf(stderr, "GNU TLS: SHA512 error: %s\n", gnutls_strerror(ret));
|
|
|
f1f986 |
+ cc = NULL;
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+}
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+/* see sph_sha3.h */
|
|
|
f1f986 |
+void
|
|
|
f1f986 |
+sph_sha512_close(void * cc, void * dst)
|
|
|
f1f986 |
+{
|
|
|
f1f986 |
+ gnutls_hash_hd_t * ctx = (gnutls_hash_hd_t*) cc;
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+ if (ctx != NULL && dst != NULL)
|
|
|
f1f986 |
+ {
|
|
|
f1f986 |
+ gnutls_hash_deinit(*(ctx), dst);
|
|
|
f1f986 |
+ cc = NULL;
|
|
|
f1f986 |
+ }
|
|
|
f1f986 |
+}
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+/* see sph_sha3.h */
|
|
|
f1f986 |
+void
|
|
|
f1f986 |
+sph_sha512(void * cc, const void * data, size_t len)
|
|
|
f1f986 |
+{
|
|
|
f1f986 |
+ gnutls_hash_hd_t * ctx = (gnutls_hash_hd_t*) cc;
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+ if (ctx != NULL && data != NULL)
|
|
|
f1f986 |
+ gnutls_hash(*(ctx), data, len);
|
|
|
f1f986 |
+}
|
|
|
f1f986 |
diff --git a/libqpdf/sha2big.c b/libqpdf/sha2big.c
|
|
|
f1f986 |
index e4aadbd..3194a10 100644
|
|
|
f1f986 |
--- a/libqpdf/sha2big.c
|
|
|
f1f986 |
+++ b/libqpdf/sha2big.c
|
|
|
f1f986 |
@@ -35,6 +35,10 @@
|
|
|
f1f986 |
|
|
|
f1f986 |
#include "sph/sph_sha2.h"
|
|
|
f1f986 |
|
|
|
f1f986 |
+#ifdef HAVE_GNUTLS
|
|
|
f1f986 |
+# include "sha2big-gnutls.c"
|
|
|
f1f986 |
+#else
|
|
|
f1f986 |
+
|
|
|
f1f986 |
#if SPH_64
|
|
|
f1f986 |
|
|
|
f1f986 |
#define CH(X, Y, Z) ((((Y) ^ (Z)) & (X)) ^ (Z))
|
|
|
f1f986 |
@@ -245,3 +249,5 @@ sph_sha384_comp(const sph_u64 msg[16], sph_u64 val[8])
|
|
|
f1f986 |
}
|
|
|
f1f986 |
|
|
|
f1f986 |
#endif
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+#endif /* HAVE_GNUTLS */
|
|
|
f1f986 |
diff --git a/libqpdf/sph/sph_sha2.h b/libqpdf/sph/sph_sha2.h
|
|
|
f1f986 |
index 4bff9cd..584c6ab 100644
|
|
|
f1f986 |
--- a/libqpdf/sph/sph_sha2.h
|
|
|
f1f986 |
+++ b/libqpdf/sph/sph_sha2.h
|
|
|
f1f986 |
@@ -47,6 +47,12 @@ extern "C" {
|
|
|
f1f986 |
#include <stddef.h>
|
|
|
f1f986 |
#include "sph_types.h"
|
|
|
f1f986 |
|
|
|
f1f986 |
+#include <qpdf/qpdf-config.h>
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+#ifdef HAVE_GNUTLS
|
|
|
f1f986 |
+# include "sph_sha2_gnutls.h"
|
|
|
f1f986 |
+#else
|
|
|
f1f986 |
+
|
|
|
f1f986 |
/**
|
|
|
f1f986 |
* Output size (in bits) for SHA-224.
|
|
|
f1f986 |
*/
|
|
|
f1f986 |
@@ -371,6 +377,8 @@ void sph_sha512_comp(const sph_u64 msg[16], sph_u64 val[8]);
|
|
|
f1f986 |
|
|
|
f1f986 |
#endif
|
|
|
f1f986 |
|
|
|
f1f986 |
+#endif /* HAVE_GNUTLS */
|
|
|
f1f986 |
+
|
|
|
f1f986 |
#ifdef __cplusplus
|
|
|
f1f986 |
}
|
|
|
f1f986 |
#endif
|
|
|
f1f986 |
diff --git a/libqpdf/sph/sph_sha2_gnutls.h b/libqpdf/sph/sph_sha2_gnutls.h
|
|
|
f1f986 |
new file mode 100644
|
|
|
f1f986 |
index 0000000..1fb26a4
|
|
|
f1f986 |
--- /dev/null
|
|
|
f1f986 |
+++ b/libqpdf/sph/sph_sha2_gnutls.h
|
|
|
f1f986 |
@@ -0,0 +1,88 @@
|
|
|
f1f986 |
+#include <qpdf/qpdf-config.h>
|
|
|
f1f986 |
+#include <gnutls/crypto.h>
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+typedef gnutls_hash_hd_t sph_sha256_context;
|
|
|
f1f986 |
+typedef gnutls_hash_hd_t sph_sha384_context;
|
|
|
f1f986 |
+typedef gnutls_hash_hd_t sph_sha512_context;
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+/**
|
|
|
f1f986 |
+ * Initialize a SHA-256 context.
|
|
|
f1f986 |
+ *
|
|
|
f1f986 |
+ * @param cc the SHA-256 context (pointer to
|
|
|
f1f986 |
+ * a sph_sha256_context )
|
|
|
f1f986 |
+ */
|
|
|
f1f986 |
+void sph_sha256_init(void *cc);
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+/**
|
|
|
f1f986 |
+ * Process some data bytes, for SHA-256.
|
|
|
f1f986 |
+ *
|
|
|
f1f986 |
+ * @param cc the SHA-224 context
|
|
|
f1f986 |
+ * @param data the input data
|
|
|
f1f986 |
+ * @param len the input data length (in bytes)
|
|
|
f1f986 |
+ */
|
|
|
f1f986 |
+void sph_sha256(void *cc, const void *data, size_t len);
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+/**
|
|
|
f1f986 |
+ * Terminate the current SHA-256 computation and output the result into the
|
|
|
f1f986 |
+ * provided buffer. The destination buffer must be wide enough to
|
|
|
f1f986 |
+ * accomodate the result (32 bytes).
|
|
|
f1f986 |
+ *
|
|
|
f1f986 |
+ * @param cc the SHA-256 context
|
|
|
f1f986 |
+ * @param dst the destination buffer
|
|
|
f1f986 |
+ */
|
|
|
f1f986 |
+void sph_sha256_close(void *cc, void *dst);
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+/**
|
|
|
f1f986 |
+ * Initialize a SHA-384 context.
|
|
|
f1f986 |
+ *
|
|
|
f1f986 |
+ * @param cc the SHA-384 context (pointer to
|
|
|
f1f986 |
+ * a sph_sha384_context )
|
|
|
f1f986 |
+ */
|
|
|
f1f986 |
+void sph_sha384_init(void *cc);
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+/**
|
|
|
f1f986 |
+ * Process some data bytes. It is acceptable that len is zero
|
|
|
f1f986 |
+ * (in which case this function does nothing).
|
|
|
f1f986 |
+ *
|
|
|
f1f986 |
+ * @param cc the SHA-384 context
|
|
|
f1f986 |
+ * @param data the input data
|
|
|
f1f986 |
+ * @param len the input data length (in bytes)
|
|
|
f1f986 |
+ */
|
|
|
f1f986 |
+void sph_sha384(void *cc, const void *data, size_t len);
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+/**
|
|
|
f1f986 |
+ * Terminate the current SHA-384 computation and output the result into the
|
|
|
f1f986 |
+ * provided buffer. The destination buffer must be wide enough to
|
|
|
f1f986 |
+ * accomodate the result (48 bytes).
|
|
|
f1f986 |
+ *
|
|
|
f1f986 |
+ * @param cc the SHA-384 context
|
|
|
f1f986 |
+ * @param dst the destination buffer
|
|
|
f1f986 |
+ */
|
|
|
f1f986 |
+void sph_sha384_close(void *cc, void *dst);
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+/**
|
|
|
f1f986 |
+ * Initialize a SHA-512 context.
|
|
|
f1f986 |
+ *
|
|
|
f1f986 |
+ * @param cc the SHA-512 context (pointer to
|
|
|
f1f986 |
+ * a sph_sha512_context )
|
|
|
f1f986 |
+ */
|
|
|
f1f986 |
+void sph_sha512_init(void *cc);
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+/**
|
|
|
f1f986 |
+ * Process some data bytes, for SHA-512.
|
|
|
f1f986 |
+ *
|
|
|
f1f986 |
+ * @param cc the SHA-384 context
|
|
|
f1f986 |
+ * @param data the input data
|
|
|
f1f986 |
+ * @param len the input data length (in bytes)
|
|
|
f1f986 |
+ */
|
|
|
f1f986 |
+void sph_sha512(void *cc, const void *data, size_t len);
|
|
|
f1f986 |
+
|
|
|
f1f986 |
+/**
|
|
|
f1f986 |
+ * Terminate the current SHA-512 computation and output the result into the
|
|
|
f1f986 |
+ * provided buffer. The destination buffer must be wide enough to
|
|
|
f1f986 |
+ * accomodate the result (64 bytes).
|
|
|
f1f986 |
+ *
|
|
|
f1f986 |
+ * @param cc the SHA-512 context
|
|
|
f1f986 |
+ * @param dst the destination buffer
|
|
|
f1f986 |
+ */
|
|
|
f1f986 |
+void sph_sha512_close(void *cc, void *dst);
|
|
|
f1f986 |
diff --git a/libqpdf/sph/sph_types.h b/libqpdf/sph/sph_types.h
|
|
|
f1f986 |
index eab09a2..36d1ff6 100644
|
|
|
f1f986 |
--- a/libqpdf/sph/sph_types.h
|
|
|
f1f986 |
+++ b/libqpdf/sph/sph_types.h
|
|
|
f1f986 |
@@ -48,6 +48,7 @@
|
|
|
f1f986 |
#define SPH_TYPES_H__
|
|
|
f1f986 |
|
|
|
f1f986 |
#include <limits.h>
|
|
|
f1f986 |
+#include <qpdf/qpdf-config.h>
|
|
|
f1f986 |
|
|
|
f1f986 |
/*
|
|
|
f1f986 |
* All our I/O functions are defined over octet streams. We do not know
|