diff options
author | Jay Berkenbilt <ejb@ql.org> | 2019-11-04 19:59:19 +0100 |
---|---|---|
committer | Jay Berkenbilt <ejb@ql.org> | 2019-11-09 14:18:02 +0100 |
commit | c8cda4f965064a9c4621d8d9f889eb7037fe72bb (patch) | |
tree | 333110d755d88709c4b196f834c6f0fa1e7b68ba | |
parent | bb427bd11774f47f553257cdc0693f77b559654d (diff) | |
download | qpdf-c8cda4f965064a9c4621d8d9f889eb7037fe72bb.tar.zst |
AES_PDF: switch to pluggable crypto
-rw-r--r-- | include/qpdf/QPDFCryptoImpl.hh | 9 | ||||
-rw-r--r-- | libqpdf/AES_PDF_native.cc | 55 | ||||
-rw-r--r-- | libqpdf/Pl_AES_PDF.cc | 36 | ||||
-rw-r--r-- | libqpdf/QPDFCrypto_native.cc | 20 | ||||
-rw-r--r-- | libqpdf/build.mk | 1 | ||||
-rw-r--r-- | libqpdf/qpdf/AES_PDF_native.hh | 25 | ||||
-rw-r--r-- | libqpdf/qpdf/Pl_AES_PDF.hh | 10 | ||||
-rw-r--r-- | libqpdf/qpdf/QPDFCrypto_native.hh | 8 |
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 |