Commit d1ffe46c04e87a297fed50ba0ff79213cdee7a5e

Authored by Jay Berkenbilt
1 parent c8cda4f9

AES_PDF: move CBC logic from pipeline to AES_PDF implementation

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();
... ...