From c8cda4f965064a9c4621d8d9f889eb7037fe72bb Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Mon, 4 Nov 2019 13:59:19 -0500 Subject: AES_PDF: switch to pluggable crypto --- libqpdf/AES_PDF_native.cc | 55 +++++++++++++++++++++++++++++++++++++++ libqpdf/Pl_AES_PDF.cc | 36 +++++++------------------ libqpdf/QPDFCrypto_native.cc | 20 ++++++++++++++ libqpdf/build.mk | 1 + libqpdf/qpdf/AES_PDF_native.hh | 25 ++++++++++++++++++ libqpdf/qpdf/Pl_AES_PDF.hh | 10 +++---- libqpdf/qpdf/QPDFCrypto_native.hh | 8 ++++++ 7 files changed, 123 insertions(+), 32 deletions(-) create mode 100644 libqpdf/AES_PDF_native.cc create mode 100644 libqpdf/qpdf/AES_PDF_native.hh (limited to 'libqpdf') 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 +#include +#include +#include +#include +#include +#include +#include +#include + +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( + new unsigned char[key_bytes], + std::default_delete()); + this->rk = std::unique_ptr( + new uint32_t[RKLENGTH(keybits)], + std::default_delete()); + 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 #include #include -#include #include +#include #include #include @@ -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( - true, new unsigned char[key_bytes]); - this->rk = PointerHolder( - 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( + new unsigned char[key_bytes], + std::default_delete()); + 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( + 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 +#include +#include + +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 key; + std::unique_ptr 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 #include -#ifdef HAVE_STDINT_H -# include -#endif +#include +#include // 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 crypto; bool encrypt; bool cbc_mode; bool first; size_t offset; // offset into memory buffer - PointerHolder key; - PointerHolder rk; + std::unique_ptr 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 #include #include +#include #include 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; std::shared_ptr rc4; std::shared_ptr sha2; + std::shared_ptr aes_pdf; }; #endif // QPDFCRYPTO_NATIVE_HH -- cgit v1.2.3-70-g09d2