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