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 | 74 | QPDF_DLL |
| 75 | 75 | virtual void RC4_finalize() = 0; |
| 76 | 76 | |
| 77 | + static size_t constexpr rijndael_buf_size = 16; | |
| 77 | 78 | QPDF_DLL |
| 78 | 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 | 82 | QPDF_DLL |
| 81 | 83 | virtual void rijndael_process( |
| 82 | 84 | unsigned char* in_data, unsigned char* out_data) = 0; | ... | ... |
libqpdf/AES_PDF_native.cc
| ... | ... | @@ -7,10 +7,14 @@ |
| 7 | 7 | #include <qpdf/QIntC.hh> |
| 8 | 8 | #include <string> |
| 9 | 9 | #include <stdlib.h> |
| 10 | +#include <qpdf/QPDFCryptoImpl.hh> | |
| 10 | 11 | |
| 11 | 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 | 15 | encrypt(encrypt), |
| 16 | + cbc_mode(cbc_mode), | |
| 17 | + cbc_block(cbc_block), | |
| 14 | 18 | nrounds(0) |
| 15 | 19 | { |
| 16 | 20 | size_t keybits = 8 * key_bytes; |
| ... | ... | @@ -44,12 +48,33 @@ AES_PDF_native::update(unsigned char* in_data, unsigned char* out_data) |
| 44 | 48 | { |
| 45 | 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 | 58 | rijndaelEncrypt(this->rk.get(), |
| 48 | 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 | 66 | else |
| 51 | 67 | { |
| 52 | 68 | rijndaelDecrypt(this->rk.get(), |
| 53 | 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 | 19 | cbc_mode(true), |
| 20 | 20 | first(true), |
| 21 | 21 | offset(0), |
| 22 | + key_bytes(key_bytes), | |
| 22 | 23 | use_zero_iv(false), |
| 23 | 24 | use_specified_iv(false), |
| 24 | 25 | disable_padding(false) |
| ... | ... | @@ -30,7 +31,6 @@ Pl_AES_PDF::Pl_AES_PDF(char const* identifier, Pipeline* next, |
| 30 | 31 | std::memset(this->inbuf, 0, this->buf_size); |
| 31 | 32 | std::memset(this->outbuf, 0, this->buf_size); |
| 32 | 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 | 36 | Pl_AES_PDF::~Pl_AES_PDF() |
| ... | ... | @@ -172,6 +172,7 @@ Pl_AES_PDF::flush(bool strip_padding) |
| 172 | 172 | if (first) |
| 173 | 173 | { |
| 174 | 174 | first = false; |
| 175 | + bool return_after_init = false; | |
| 175 | 176 | if (this->cbc_mode) |
| 176 | 177 | { |
| 177 | 178 | if (encrypt) |
| ... | ... | @@ -196,37 +197,25 @@ Pl_AES_PDF::flush(bool strip_padding) |
| 196 | 197 | // vector. There's nothing to write at this time. |
| 197 | 198 | memcpy(this->cbc_block, this->inbuf, this->buf_size); |
| 198 | 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 | 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 | 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 | 216 | else |
| 220 | 217 | { |
| 221 | 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 | 220 | unsigned int bytes = this->buf_size; |
| 232 | 221 | if (strip_padding) | ... | ... |
libqpdf/QPDFCrypto_native.cc
| ... | ... | @@ -69,10 +69,12 @@ QPDFCrypto_native::SHA2_digest() |
| 69 | 69 | |
| 70 | 70 | void |
| 71 | 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 | 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 | 80 | void | ... | ... |
libqpdf/qpdf/AES_PDF_native.hh
| ... | ... | @@ -10,13 +10,15 @@ class AES_PDF_native |
| 10 | 10 | public: |
| 11 | 11 | // key should be a pointer to key_bytes bytes of data |
| 12 | 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 | 14 | ~AES_PDF_native(); |
| 15 | 15 | |
| 16 | 16 | void update(unsigned char* in_data, unsigned char* out_data); |
| 17 | 17 | |
| 18 | 18 | private: |
| 19 | 19 | bool encrypt; |
| 20 | + bool cbc_mode; | |
| 21 | + unsigned char* cbc_block; | |
| 20 | 22 | std::unique_ptr<unsigned char[]> key; |
| 21 | 23 | std::unique_ptr<uint32_t[]> rk; |
| 22 | 24 | unsigned int nrounds; | ... | ... |
libqpdf/qpdf/Pl_AES_PDF.hh
| ... | ... | @@ -2,7 +2,6 @@ |
| 2 | 2 | #define PL_AES_PDF_HH |
| 3 | 3 | |
| 4 | 4 | #include <qpdf/Pipeline.hh> |
| 5 | -#include <qpdf/qpdf-config.h> | |
| 6 | 5 | #include <qpdf/QPDFCryptoImpl.hh> |
| 7 | 6 | #include <memory> |
| 8 | 7 | |
| ... | ... | @@ -47,7 +46,7 @@ class Pl_AES_PDF: public Pipeline |
| 47 | 46 | void flush(bool discard_padding); |
| 48 | 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 | 50 | static bool use_static_iv; |
| 52 | 51 | |
| 53 | 52 | std::shared_ptr<QPDFCryptoImpl> crypto; |
| ... | ... | @@ -56,6 +55,7 @@ class Pl_AES_PDF: public Pipeline |
| 56 | 55 | bool first; |
| 57 | 56 | size_t offset; // offset into memory buffer |
| 58 | 57 | std::unique_ptr<unsigned char[]> key; |
| 58 | + size_t key_bytes; | |
| 59 | 59 | unsigned char inbuf[buf_size]; |
| 60 | 60 | unsigned char outbuf[buf_size]; |
| 61 | 61 | unsigned char cbc_block[buf_size]; | ... | ... |
libqpdf/qpdf/QPDFCrypto_native.hh
| ... | ... | @@ -33,7 +33,8 @@ class QPDFCrypto_native: public QPDFCryptoImpl |
| 33 | 33 | virtual std::string SHA2_digest(); |
| 34 | 34 | |
| 35 | 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 | 38 | virtual void rijndael_process( |
| 38 | 39 | unsigned char* in_data, unsigned char* out_data); |
| 39 | 40 | virtual void rijndael_finalize(); | ... | ... |