aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2019-11-04 19:59:19 +0100
committerJay Berkenbilt <ejb@ql.org>2019-11-09 14:18:02 +0100
commitc8cda4f965064a9c4621d8d9f889eb7037fe72bb (patch)
tree333110d755d88709c4b196f834c6f0fa1e7b68ba
parentbb427bd11774f47f553257cdc0693f77b559654d (diff)
downloadqpdf-c8cda4f965064a9c4621d8d9f889eb7037fe72bb.tar.zst
AES_PDF: switch to pluggable crypto
-rw-r--r--include/qpdf/QPDFCryptoImpl.hh9
-rw-r--r--libqpdf/AES_PDF_native.cc55
-rw-r--r--libqpdf/Pl_AES_PDF.cc36
-rw-r--r--libqpdf/QPDFCrypto_native.cc20
-rw-r--r--libqpdf/build.mk1
-rw-r--r--libqpdf/qpdf/AES_PDF_native.hh25
-rw-r--r--libqpdf/qpdf/Pl_AES_PDF.hh10
-rw-r--r--libqpdf/qpdf/QPDFCrypto_native.hh8
8 files changed, 132 insertions, 32 deletions
diff --git a/include/qpdf/QPDFCryptoImpl.hh b/include/qpdf/QPDFCryptoImpl.hh
index 09803a79..edeea0d3 100644
--- a/include/qpdf/QPDFCryptoImpl.hh
+++ b/include/qpdf/QPDFCryptoImpl.hh
@@ -73,6 +73,15 @@ class QPDF_DLL_CLASS QPDFCryptoImpl
unsigned char* out_data = 0) = 0;
QPDF_DLL
virtual void RC4_finalize() = 0;
+
+ QPDF_DLL
+ virtual void rijndael_init(
+ bool encrypt, unsigned char const* key_data, size_t key_len) = 0;
+ QPDF_DLL
+ virtual void rijndael_process(
+ unsigned char* in_data, unsigned char* out_data) = 0;
+ QPDF_DLL
+ virtual void rijndael_finalize() = 0;
};
#endif // QPDFCRYPTOIMPL_HH
diff --git a/libqpdf/AES_PDF_native.cc b/libqpdf/AES_PDF_native.cc
new file mode 100644
index 00000000..d6907ee3
--- /dev/null
+++ b/libqpdf/AES_PDF_native.cc
@@ -0,0 +1,55 @@
+#include <qpdf/AES_PDF_native.hh>
+#include <qpdf/QUtil.hh>
+#include <cstring>
+#include <assert.h>
+#include <stdexcept>
+#include <qpdf/rijndael.h>
+#include <qpdf/QIntC.hh>
+#include <string>
+#include <stdlib.h>
+
+AES_PDF_native::AES_PDF_native(bool encrypt, unsigned char const* key,
+ size_t key_bytes) :
+ encrypt(encrypt),
+ nrounds(0)
+{
+ size_t keybits = 8 * key_bytes;
+ this->key = std::unique_ptr<unsigned char[]>(
+ new unsigned char[key_bytes],
+ std::default_delete<unsigned char[]>());
+ this->rk = std::unique_ptr<uint32_t[]>(
+ new uint32_t[RKLENGTH(keybits)],
+ std::default_delete<uint32_t[]>());
+ size_t rk_bytes = RKLENGTH(keybits) * sizeof(uint32_t);
+ std::memcpy(this->key.get(), key, key_bytes);
+ std::memset(this->rk.get(), 0, rk_bytes);
+ if (encrypt)
+ {
+ this->nrounds = rijndaelSetupEncrypt(
+ this->rk.get(), this->key.get(), keybits);
+ }
+ else
+ {
+ this->nrounds = rijndaelSetupDecrypt(
+ this->rk.get(), this->key.get(), keybits);
+ }
+}
+
+AES_PDF_native::~AES_PDF_native()
+{
+}
+
+void
+AES_PDF_native::update(unsigned char* in_data, unsigned char* out_data)
+{
+ if (this->encrypt)
+ {
+ rijndaelEncrypt(this->rk.get(),
+ this->nrounds, in_data, out_data);
+ }
+ else
+ {
+ rijndaelDecrypt(this->rk.get(),
+ this->nrounds, in_data, out_data);
+ }
+}
diff --git a/libqpdf/Pl_AES_PDF.cc b/libqpdf/Pl_AES_PDF.cc
index 1099ab13..a6756035 100644
--- a/libqpdf/Pl_AES_PDF.cc
+++ b/libqpdf/Pl_AES_PDF.cc
@@ -3,8 +3,8 @@
#include <cstring>
#include <assert.h>
#include <stdexcept>
-#include <qpdf/rijndael.h>
#include <qpdf/QIntC.hh>
+#include <qpdf/QPDFCryptoProvider.hh>
#include <string>
#include <stdlib.h>
@@ -14,38 +14,23 @@ Pl_AES_PDF::Pl_AES_PDF(char const* identifier, Pipeline* next,
bool encrypt, unsigned char const* key,
size_t key_bytes) :
Pipeline(identifier, next),
+ crypto(QPDFCryptoProvider::getImpl()),
encrypt(encrypt),
cbc_mode(true),
first(true),
offset(0),
- nrounds(0),
use_zero_iv(false),
use_specified_iv(false),
disable_padding(false)
{
- size_t keybits = 8 * key_bytes;
- assert(key_bytes == KEYLENGTH(keybits));
- this->key = PointerHolder<unsigned char>(
- true, new unsigned char[key_bytes]);
- this->rk = PointerHolder<uint32_t>(
- true, new uint32_t[RKLENGTH(keybits)]);
- size_t rk_bytes = RKLENGTH(keybits) * sizeof(uint32_t);
- std::memcpy(this->key.getPointer(), key, key_bytes);
- std::memset(this->rk.getPointer(), 0, rk_bytes);
+ this->key = std::unique_ptr<unsigned char[]>(
+ new unsigned char[key_bytes],
+ std::default_delete<unsigned char[]>());
+ std::memcpy(this->key.get(), key, key_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);
- if (encrypt)
- {
- this->nrounds = rijndaelSetupEncrypt(
- this->rk.getPointer(), this->key.getPointer(), keybits);
- }
- else
- {
- this->nrounds = rijndaelSetupDecrypt(
- this->rk.getPointer(), this->key.getPointer(), keybits);
- }
- assert(this->nrounds == NROUNDS(keybits));
+ this->crypto->rijndael_init(encrypt, this->key.get(), key_bytes);
}
Pl_AES_PDF::~Pl_AES_PDF()
@@ -148,6 +133,7 @@ Pl_AES_PDF::finish()
}
flush(! this->disable_padding);
}
+ this->crypto->rijndael_finalize();
getNext()->finish();
}
@@ -224,8 +210,7 @@ Pl_AES_PDF::flush(bool strip_padding)
this->inbuf[i] ^= this->cbc_block[i];
}
}
- rijndaelEncrypt(this->rk.getPointer(),
- this->nrounds, this->inbuf, this->outbuf);
+ this->crypto->rijndael_process(this->inbuf, this->outbuf);
if (this->cbc_mode)
{
memcpy(this->cbc_block, this->outbuf, this->buf_size);
@@ -233,8 +218,7 @@ Pl_AES_PDF::flush(bool strip_padding)
}
else
{
- rijndaelDecrypt(this->rk.getPointer(),
- this->nrounds, this->inbuf, this->outbuf);
+ this->crypto->rijndael_process(this->inbuf, this->outbuf);
if (this->cbc_mode)
{
for (unsigned int i = 0; i < this->buf_size; ++i)
diff --git a/libqpdf/QPDFCrypto_native.cc b/libqpdf/QPDFCrypto_native.cc
index b56c5373..971897dc 100644
--- a/libqpdf/QPDFCrypto_native.cc
+++ b/libqpdf/QPDFCrypto_native.cc
@@ -66,3 +66,23 @@ QPDFCrypto_native::SHA2_digest()
{
return this->sha2->getRawDigest();
}
+
+void
+QPDFCrypto_native::rijndael_init(
+ bool encrypt, unsigned char const* key_data, size_t key_len)
+{
+ this->aes_pdf = std::make_shared<AES_PDF_native>(
+ encrypt, key_data, key_len);
+}
+
+void
+QPDFCrypto_native::rijndael_process(unsigned char* in_data,
+ unsigned char* out_data)
+{
+ this->aes_pdf->update(in_data, out_data);
+}
+
+void
+QPDFCrypto_native::rijndael_finalize()
+{
+}
diff --git a/libqpdf/build.mk b/libqpdf/build.mk
index d405e27c..370033c5 100644
--- a/libqpdf/build.mk
+++ b/libqpdf/build.mk
@@ -5,6 +5,7 @@ LDFLAGS_libqpdf = -Llibqpdf/$(OUTPUT_DIR)
LIBS_libqpdf = -lqpdf
SRCS_libqpdf = \
+ libqpdf/AES_PDF_native.cc \
libqpdf/BitStream.cc \
libqpdf/BitWriter.cc \
libqpdf/Buffer.cc \
diff --git a/libqpdf/qpdf/AES_PDF_native.hh b/libqpdf/qpdf/AES_PDF_native.hh
new file mode 100644
index 00000000..f663533b
--- /dev/null
+++ b/libqpdf/qpdf/AES_PDF_native.hh
@@ -0,0 +1,25 @@
+#ifndef AES_PDF_NATIVE_HH
+#define AES_PDF_NATIVE_HH
+
+#include <cstdint>
+#include <cstring>
+#include <memory>
+
+class AES_PDF_native
+{
+ public:
+ // key should be a pointer to key_bytes bytes of data
+ AES_PDF_native(bool encrypt, unsigned char const* key,
+ size_t key_bytes);
+ ~AES_PDF_native();
+
+ void update(unsigned char* in_data, unsigned char* out_data);
+
+ private:
+ bool encrypt;
+ std::unique_ptr<unsigned char[]> key;
+ std::unique_ptr<uint32_t[]> rk;
+ unsigned int nrounds;
+};
+
+#endif // AES_PDF_NATIVE_HH
diff --git a/libqpdf/qpdf/Pl_AES_PDF.hh b/libqpdf/qpdf/Pl_AES_PDF.hh
index 31cc28f9..f8f44c70 100644
--- a/libqpdf/qpdf/Pl_AES_PDF.hh
+++ b/libqpdf/qpdf/Pl_AES_PDF.hh
@@ -3,9 +3,8 @@
#include <qpdf/Pipeline.hh>
#include <qpdf/qpdf-config.h>
-#ifdef HAVE_STDINT_H
-# include <stdint.h>
-#endif
+#include <qpdf/QPDFCryptoImpl.hh>
+#include <memory>
// This pipeline implements AES-128 and AES-256 with CBC and block
// padding as specified in the PDF specification.
@@ -51,17 +50,16 @@ class Pl_AES_PDF: public Pipeline
static unsigned int const buf_size = 16;
static bool use_static_iv;
+ std::shared_ptr<QPDFCryptoImpl> crypto;
bool encrypt;
bool cbc_mode;
bool first;
size_t offset; // offset into memory buffer
- PointerHolder<unsigned char> key;
- PointerHolder<uint32_t> rk;
+ std::unique_ptr<unsigned char[]> key;
unsigned char inbuf[buf_size];
unsigned char outbuf[buf_size];
unsigned char cbc_block[buf_size];
unsigned char specified_iv[buf_size];
- unsigned int nrounds;
bool use_zero_iv;
bool use_specified_iv;
bool disable_padding;
diff --git a/libqpdf/qpdf/QPDFCrypto_native.hh b/libqpdf/qpdf/QPDFCrypto_native.hh
index d015dc10..1f006d3c 100644
--- a/libqpdf/qpdf/QPDFCrypto_native.hh
+++ b/libqpdf/qpdf/QPDFCrypto_native.hh
@@ -6,6 +6,7 @@
#include <qpdf/MD5_native.hh>
#include <qpdf/RC4_native.hh>
#include <qpdf/SHA2_native.hh>
+#include <qpdf/AES_PDF_native.hh>
#include <memory>
class QPDFCrypto_native: public QPDFCryptoImpl
@@ -31,10 +32,17 @@ class QPDFCrypto_native: public QPDFCryptoImpl
virtual void SHA2_finalize();
virtual std::string SHA2_digest();
+ virtual void rijndael_init(
+ bool encrypt, unsigned char const* key_data, size_t key_len);
+ virtual void rijndael_process(
+ unsigned char* in_data, unsigned char* out_data);
+ virtual void rijndael_finalize();
+
private:
std::shared_ptr<MD5_native> md5;
std::shared_ptr<RC4_native> rc4;
std::shared_ptr<SHA2_native> sha2;
+ std::shared_ptr<AES_PDF_native> aes_pdf;
};
#endif // QPDFCRYPTO_NATIVE_HH