Commit d1ffe46c04e87a297fed50ba0ff79213cdee7a5e
1 parent
c8cda4f9
AES_PDF: move CBC logic from pipeline to AES_PDF implementation
Showing
7 changed files
with
50 additions
and
29 deletions
include/qpdf/QPDFCryptoImpl.hh
| @@ -74,9 +74,11 @@ class QPDF_DLL_CLASS QPDFCryptoImpl | @@ -74,9 +74,11 @@ class QPDF_DLL_CLASS QPDFCryptoImpl | ||
| 74 | QPDF_DLL | 74 | QPDF_DLL |
| 75 | virtual void RC4_finalize() = 0; | 75 | virtual void RC4_finalize() = 0; |
| 76 | 76 | ||
| 77 | + static size_t constexpr rijndael_buf_size = 16; | ||
| 77 | QPDF_DLL | 78 | QPDF_DLL |
| 78 | virtual void rijndael_init( | 79 | virtual void rijndael_init( |
| 79 | - bool encrypt, unsigned char const* key_data, size_t key_len) = 0; | 80 | + bool encrypt, unsigned char const* key_data, size_t key_len, |
| 81 | + bool cbc_mode, unsigned char* cbc_block) = 0; | ||
| 80 | QPDF_DLL | 82 | QPDF_DLL |
| 81 | virtual void rijndael_process( | 83 | virtual void rijndael_process( |
| 82 | unsigned char* in_data, unsigned char* out_data) = 0; | 84 | unsigned char* in_data, unsigned char* out_data) = 0; |
libqpdf/AES_PDF_native.cc
| @@ -7,10 +7,14 @@ | @@ -7,10 +7,14 @@ | ||
| 7 | #include <qpdf/QIntC.hh> | 7 | #include <qpdf/QIntC.hh> |
| 8 | #include <string> | 8 | #include <string> |
| 9 | #include <stdlib.h> | 9 | #include <stdlib.h> |
| 10 | +#include <qpdf/QPDFCryptoImpl.hh> | ||
| 10 | 11 | ||
| 11 | AES_PDF_native::AES_PDF_native(bool encrypt, unsigned char const* key, | 12 | AES_PDF_native::AES_PDF_native(bool encrypt, unsigned char const* key, |
| 12 | - size_t key_bytes) : | 13 | + size_t key_bytes, bool cbc_mode, |
| 14 | + unsigned char* cbc_block) : | ||
| 13 | encrypt(encrypt), | 15 | encrypt(encrypt), |
| 16 | + cbc_mode(cbc_mode), | ||
| 17 | + cbc_block(cbc_block), | ||
| 14 | nrounds(0) | 18 | nrounds(0) |
| 15 | { | 19 | { |
| 16 | size_t keybits = 8 * key_bytes; | 20 | size_t keybits = 8 * key_bytes; |
| @@ -44,12 +48,33 @@ AES_PDF_native::update(unsigned char* in_data, unsigned char* out_data) | @@ -44,12 +48,33 @@ AES_PDF_native::update(unsigned char* in_data, unsigned char* out_data) | ||
| 44 | { | 48 | { |
| 45 | if (this->encrypt) | 49 | if (this->encrypt) |
| 46 | { | 50 | { |
| 51 | + if (this->cbc_mode) | ||
| 52 | + { | ||
| 53 | + for (size_t i = 0; i < QPDFCryptoImpl::rijndael_buf_size; ++i) | ||
| 54 | + { | ||
| 55 | + in_data[i] ^= this->cbc_block[i]; | ||
| 56 | + } | ||
| 57 | + } | ||
| 47 | rijndaelEncrypt(this->rk.get(), | 58 | rijndaelEncrypt(this->rk.get(), |
| 48 | this->nrounds, in_data, out_data); | 59 | this->nrounds, in_data, out_data); |
| 60 | + if (this->cbc_mode) | ||
| 61 | + { | ||
| 62 | + memcpy(this->cbc_block, out_data, | ||
| 63 | + QPDFCryptoImpl::rijndael_buf_size); | ||
| 64 | + } | ||
| 49 | } | 65 | } |
| 50 | else | 66 | else |
| 51 | { | 67 | { |
| 52 | rijndaelDecrypt(this->rk.get(), | 68 | rijndaelDecrypt(this->rk.get(), |
| 53 | this->nrounds, in_data, out_data); | 69 | this->nrounds, in_data, out_data); |
| 70 | + if (this->cbc_mode) | ||
| 71 | + { | ||
| 72 | + for (size_t i = 0; i < QPDFCryptoImpl::rijndael_buf_size; ++i) | ||
| 73 | + { | ||
| 74 | + out_data[i] ^= this->cbc_block[i]; | ||
| 75 | + } | ||
| 76 | + memcpy(this->cbc_block, in_data, | ||
| 77 | + QPDFCryptoImpl::rijndael_buf_size); | ||
| 78 | + } | ||
| 54 | } | 79 | } |
| 55 | } | 80 | } |
libqpdf/Pl_AES_PDF.cc
| @@ -19,6 +19,7 @@ Pl_AES_PDF::Pl_AES_PDF(char const* identifier, Pipeline* next, | @@ -19,6 +19,7 @@ Pl_AES_PDF::Pl_AES_PDF(char const* identifier, Pipeline* next, | ||
| 19 | cbc_mode(true), | 19 | cbc_mode(true), |
| 20 | first(true), | 20 | first(true), |
| 21 | offset(0), | 21 | offset(0), |
| 22 | + key_bytes(key_bytes), | ||
| 22 | use_zero_iv(false), | 23 | use_zero_iv(false), |
| 23 | use_specified_iv(false), | 24 | use_specified_iv(false), |
| 24 | disable_padding(false) | 25 | disable_padding(false) |
| @@ -30,7 +31,6 @@ Pl_AES_PDF::Pl_AES_PDF(char const* identifier, Pipeline* next, | @@ -30,7 +31,6 @@ Pl_AES_PDF::Pl_AES_PDF(char const* identifier, Pipeline* next, | ||
| 30 | std::memset(this->inbuf, 0, this->buf_size); | 31 | std::memset(this->inbuf, 0, this->buf_size); |
| 31 | std::memset(this->outbuf, 0, this->buf_size); | 32 | std::memset(this->outbuf, 0, this->buf_size); |
| 32 | std::memset(this->cbc_block, 0, this->buf_size); | 33 | std::memset(this->cbc_block, 0, this->buf_size); |
| 33 | - this->crypto->rijndael_init(encrypt, this->key.get(), key_bytes); | ||
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | Pl_AES_PDF::~Pl_AES_PDF() | 36 | Pl_AES_PDF::~Pl_AES_PDF() |
| @@ -172,6 +172,7 @@ Pl_AES_PDF::flush(bool strip_padding) | @@ -172,6 +172,7 @@ Pl_AES_PDF::flush(bool strip_padding) | ||
| 172 | if (first) | 172 | if (first) |
| 173 | { | 173 | { |
| 174 | first = false; | 174 | first = false; |
| 175 | + bool return_after_init = false; | ||
| 175 | if (this->cbc_mode) | 176 | if (this->cbc_mode) |
| 176 | { | 177 | { |
| 177 | if (encrypt) | 178 | if (encrypt) |
| @@ -196,37 +197,25 @@ Pl_AES_PDF::flush(bool strip_padding) | @@ -196,37 +197,25 @@ Pl_AES_PDF::flush(bool strip_padding) | ||
| 196 | // vector. There's nothing to write at this time. | 197 | // vector. There's nothing to write at this time. |
| 197 | memcpy(this->cbc_block, this->inbuf, this->buf_size); | 198 | memcpy(this->cbc_block, this->inbuf, this->buf_size); |
| 198 | this->offset = 0; | 199 | this->offset = 0; |
| 199 | - return; | 200 | + return_after_init = true; |
| 200 | } | 201 | } |
| 201 | } | 202 | } |
| 203 | + this->crypto->rijndael_init( | ||
| 204 | + encrypt, this->key.get(), key_bytes, | ||
| 205 | + this->cbc_mode, this->cbc_block); | ||
| 206 | + if (return_after_init) | ||
| 207 | + { | ||
| 208 | + return; | ||
| 209 | + } | ||
| 202 | } | 210 | } |
| 203 | 211 | ||
| 204 | if (this->encrypt) | 212 | if (this->encrypt) |
| 205 | { | 213 | { |
| 206 | - if (this->cbc_mode) | ||
| 207 | - { | ||
| 208 | - for (unsigned int i = 0; i < this->buf_size; ++i) | ||
| 209 | - { | ||
| 210 | - this->inbuf[i] ^= this->cbc_block[i]; | ||
| 211 | - } | ||
| 212 | - } | ||
| 213 | this->crypto->rijndael_process(this->inbuf, this->outbuf); | 214 | this->crypto->rijndael_process(this->inbuf, this->outbuf); |
| 214 | - if (this->cbc_mode) | ||
| 215 | - { | ||
| 216 | - memcpy(this->cbc_block, this->outbuf, this->buf_size); | ||
| 217 | - } | ||
| 218 | } | 215 | } |
| 219 | else | 216 | else |
| 220 | { | 217 | { |
| 221 | this->crypto->rijndael_process(this->inbuf, this->outbuf); | 218 | this->crypto->rijndael_process(this->inbuf, this->outbuf); |
| 222 | - if (this->cbc_mode) | ||
| 223 | - { | ||
| 224 | - for (unsigned int i = 0; i < this->buf_size; ++i) | ||
| 225 | - { | ||
| 226 | - this->outbuf[i] ^= this->cbc_block[i]; | ||
| 227 | - } | ||
| 228 | - memcpy(this->cbc_block, this->inbuf, this->buf_size); | ||
| 229 | - } | ||
| 230 | } | 219 | } |
| 231 | unsigned int bytes = this->buf_size; | 220 | unsigned int bytes = this->buf_size; |
| 232 | if (strip_padding) | 221 | if (strip_padding) |
libqpdf/QPDFCrypto_native.cc
| @@ -69,10 +69,12 @@ QPDFCrypto_native::SHA2_digest() | @@ -69,10 +69,12 @@ QPDFCrypto_native::SHA2_digest() | ||
| 69 | 69 | ||
| 70 | void | 70 | void |
| 71 | QPDFCrypto_native::rijndael_init( | 71 | QPDFCrypto_native::rijndael_init( |
| 72 | - bool encrypt, unsigned char const* key_data, size_t key_len) | 72 | + bool encrypt, unsigned char const* key_data, size_t key_len, |
| 73 | + bool cbc_mode, unsigned char* cbc_block) | ||
| 74 | + | ||
| 73 | { | 75 | { |
| 74 | this->aes_pdf = std::make_shared<AES_PDF_native>( | 76 | this->aes_pdf = std::make_shared<AES_PDF_native>( |
| 75 | - encrypt, key_data, key_len); | 77 | + encrypt, key_data, key_len, cbc_mode, cbc_block); |
| 76 | } | 78 | } |
| 77 | 79 | ||
| 78 | void | 80 | void |
libqpdf/qpdf/AES_PDF_native.hh
| @@ -10,13 +10,15 @@ class AES_PDF_native | @@ -10,13 +10,15 @@ class AES_PDF_native | ||
| 10 | public: | 10 | public: |
| 11 | // key should be a pointer to key_bytes bytes of data | 11 | // key should be a pointer to key_bytes bytes of data |
| 12 | AES_PDF_native(bool encrypt, unsigned char const* key, | 12 | AES_PDF_native(bool encrypt, unsigned char const* key, |
| 13 | - size_t key_bytes); | 13 | + size_t key_bytes, bool cbc_mode, unsigned char* cbc_block); |
| 14 | ~AES_PDF_native(); | 14 | ~AES_PDF_native(); |
| 15 | 15 | ||
| 16 | void update(unsigned char* in_data, unsigned char* out_data); | 16 | void update(unsigned char* in_data, unsigned char* out_data); |
| 17 | 17 | ||
| 18 | private: | 18 | private: |
| 19 | bool encrypt; | 19 | bool encrypt; |
| 20 | + bool cbc_mode; | ||
| 21 | + unsigned char* cbc_block; | ||
| 20 | std::unique_ptr<unsigned char[]> key; | 22 | std::unique_ptr<unsigned char[]> key; |
| 21 | std::unique_ptr<uint32_t[]> rk; | 23 | std::unique_ptr<uint32_t[]> rk; |
| 22 | unsigned int nrounds; | 24 | unsigned int nrounds; |
libqpdf/qpdf/Pl_AES_PDF.hh
| @@ -2,7 +2,6 @@ | @@ -2,7 +2,6 @@ | ||
| 2 | #define PL_AES_PDF_HH | 2 | #define PL_AES_PDF_HH |
| 3 | 3 | ||
| 4 | #include <qpdf/Pipeline.hh> | 4 | #include <qpdf/Pipeline.hh> |
| 5 | -#include <qpdf/qpdf-config.h> | ||
| 6 | #include <qpdf/QPDFCryptoImpl.hh> | 5 | #include <qpdf/QPDFCryptoImpl.hh> |
| 7 | #include <memory> | 6 | #include <memory> |
| 8 | 7 | ||
| @@ -47,7 +46,7 @@ class Pl_AES_PDF: public Pipeline | @@ -47,7 +46,7 @@ class Pl_AES_PDF: public Pipeline | ||
| 47 | void flush(bool discard_padding); | 46 | void flush(bool discard_padding); |
| 48 | void initializeVector(); | 47 | void initializeVector(); |
| 49 | 48 | ||
| 50 | - static unsigned int const buf_size = 16; | 49 | + static unsigned int const buf_size = QPDFCryptoImpl::rijndael_buf_size; |
| 51 | static bool use_static_iv; | 50 | static bool use_static_iv; |
| 52 | 51 | ||
| 53 | std::shared_ptr<QPDFCryptoImpl> crypto; | 52 | std::shared_ptr<QPDFCryptoImpl> crypto; |
| @@ -56,6 +55,7 @@ class Pl_AES_PDF: public Pipeline | @@ -56,6 +55,7 @@ class Pl_AES_PDF: public Pipeline | ||
| 56 | bool first; | 55 | bool first; |
| 57 | size_t offset; // offset into memory buffer | 56 | size_t offset; // offset into memory buffer |
| 58 | std::unique_ptr<unsigned char[]> key; | 57 | std::unique_ptr<unsigned char[]> key; |
| 58 | + size_t key_bytes; | ||
| 59 | unsigned char inbuf[buf_size]; | 59 | unsigned char inbuf[buf_size]; |
| 60 | unsigned char outbuf[buf_size]; | 60 | unsigned char outbuf[buf_size]; |
| 61 | unsigned char cbc_block[buf_size]; | 61 | unsigned char cbc_block[buf_size]; |
libqpdf/qpdf/QPDFCrypto_native.hh
| @@ -33,7 +33,8 @@ class QPDFCrypto_native: public QPDFCryptoImpl | @@ -33,7 +33,8 @@ class QPDFCrypto_native: public QPDFCryptoImpl | ||
| 33 | virtual std::string SHA2_digest(); | 33 | virtual std::string SHA2_digest(); |
| 34 | 34 | ||
| 35 | virtual void rijndael_init( | 35 | virtual void rijndael_init( |
| 36 | - bool encrypt, unsigned char const* key_data, size_t key_len); | 36 | + bool encrypt, unsigned char const* key_data, size_t key_len, |
| 37 | + bool cbc_mode, unsigned char* cbc_block); | ||
| 37 | virtual void rijndael_process( | 38 | virtual void rijndael_process( |
| 38 | unsigned char* in_data, unsigned char* out_data); | 39 | unsigned char* in_data, unsigned char* out_data); |
| 39 | virtual void rijndael_finalize(); | 40 | virtual void rijndael_finalize(); |