Commit c8cda4f965064a9c4621d8d9f889eb7037fe72bb

Authored by Jay Berkenbilt
1 parent bb427bd1

AES_PDF: switch to pluggable crypto

include/qpdf/QPDFCryptoImpl.hh
@@ -73,6 +73,15 @@ class QPDF_DLL_CLASS QPDFCryptoImpl @@ -73,6 +73,15 @@ class QPDF_DLL_CLASS QPDFCryptoImpl
73 unsigned char* out_data = 0) = 0; 73 unsigned char* out_data = 0) = 0;
74 QPDF_DLL 74 QPDF_DLL
75 virtual void RC4_finalize() = 0; 75 virtual void RC4_finalize() = 0;
  76 +
  77 + QPDF_DLL
  78 + virtual void rijndael_init(
  79 + bool encrypt, unsigned char const* key_data, size_t key_len) = 0;
  80 + QPDF_DLL
  81 + virtual void rijndael_process(
  82 + unsigned char* in_data, unsigned char* out_data) = 0;
  83 + QPDF_DLL
  84 + virtual void rijndael_finalize() = 0;
76 }; 85 };
77 86
78 #endif // QPDFCRYPTOIMPL_HH 87 #endif // QPDFCRYPTOIMPL_HH
libqpdf/AES_PDF_native.cc 0 → 100644
  1 +#include <qpdf/AES_PDF_native.hh>
  2 +#include <qpdf/QUtil.hh>
  3 +#include <cstring>
  4 +#include <assert.h>
  5 +#include <stdexcept>
  6 +#include <qpdf/rijndael.h>
  7 +#include <qpdf/QIntC.hh>
  8 +#include <string>
  9 +#include <stdlib.h>
  10 +
  11 +AES_PDF_native::AES_PDF_native(bool encrypt, unsigned char const* key,
  12 + size_t key_bytes) :
  13 + encrypt(encrypt),
  14 + nrounds(0)
  15 +{
  16 + size_t keybits = 8 * key_bytes;
  17 + this->key = std::unique_ptr<unsigned char[]>(
  18 + new unsigned char[key_bytes],
  19 + std::default_delete<unsigned char[]>());
  20 + this->rk = std::unique_ptr<uint32_t[]>(
  21 + new uint32_t[RKLENGTH(keybits)],
  22 + std::default_delete<uint32_t[]>());
  23 + size_t rk_bytes = RKLENGTH(keybits) * sizeof(uint32_t);
  24 + std::memcpy(this->key.get(), key, key_bytes);
  25 + std::memset(this->rk.get(), 0, rk_bytes);
  26 + if (encrypt)
  27 + {
  28 + this->nrounds = rijndaelSetupEncrypt(
  29 + this->rk.get(), this->key.get(), keybits);
  30 + }
  31 + else
  32 + {
  33 + this->nrounds = rijndaelSetupDecrypt(
  34 + this->rk.get(), this->key.get(), keybits);
  35 + }
  36 +}
  37 +
  38 +AES_PDF_native::~AES_PDF_native()
  39 +{
  40 +}
  41 +
  42 +void
  43 +AES_PDF_native::update(unsigned char* in_data, unsigned char* out_data)
  44 +{
  45 + if (this->encrypt)
  46 + {
  47 + rijndaelEncrypt(this->rk.get(),
  48 + this->nrounds, in_data, out_data);
  49 + }
  50 + else
  51 + {
  52 + rijndaelDecrypt(this->rk.get(),
  53 + this->nrounds, in_data, out_data);
  54 + }
  55 +}
libqpdf/Pl_AES_PDF.cc
@@ -3,8 +3,8 @@ @@ -3,8 +3,8 @@
3 #include <cstring> 3 #include <cstring>
4 #include <assert.h> 4 #include <assert.h>
5 #include <stdexcept> 5 #include <stdexcept>
6 -#include <qpdf/rijndael.h>  
7 #include <qpdf/QIntC.hh> 6 #include <qpdf/QIntC.hh>
  7 +#include <qpdf/QPDFCryptoProvider.hh>
8 #include <string> 8 #include <string>
9 #include <stdlib.h> 9 #include <stdlib.h>
10 10
@@ -14,38 +14,23 @@ Pl_AES_PDF::Pl_AES_PDF(char const* identifier, Pipeline* next, @@ -14,38 +14,23 @@ Pl_AES_PDF::Pl_AES_PDF(char const* identifier, Pipeline* next,
14 bool encrypt, unsigned char const* key, 14 bool encrypt, unsigned char const* key,
15 size_t key_bytes) : 15 size_t key_bytes) :
16 Pipeline(identifier, next), 16 Pipeline(identifier, next),
  17 + crypto(QPDFCryptoProvider::getImpl()),
17 encrypt(encrypt), 18 encrypt(encrypt),
18 cbc_mode(true), 19 cbc_mode(true),
19 first(true), 20 first(true),
20 offset(0), 21 offset(0),
21 - nrounds(0),  
22 use_zero_iv(false), 22 use_zero_iv(false),
23 use_specified_iv(false), 23 use_specified_iv(false),
24 disable_padding(false) 24 disable_padding(false)
25 { 25 {
26 - size_t keybits = 8 * key_bytes;  
27 - assert(key_bytes == KEYLENGTH(keybits));  
28 - this->key = PointerHolder<unsigned char>(  
29 - true, new unsigned char[key_bytes]);  
30 - this->rk = PointerHolder<uint32_t>(  
31 - true, new uint32_t[RKLENGTH(keybits)]);  
32 - size_t rk_bytes = RKLENGTH(keybits) * sizeof(uint32_t);  
33 - std::memcpy(this->key.getPointer(), key, key_bytes);  
34 - std::memset(this->rk.getPointer(), 0, rk_bytes); 26 + this->key = std::unique_ptr<unsigned char[]>(
  27 + new unsigned char[key_bytes],
  28 + std::default_delete<unsigned char[]>());
  29 + std::memcpy(this->key.get(), key, key_bytes);
35 std::memset(this->inbuf, 0, this->buf_size); 30 std::memset(this->inbuf, 0, this->buf_size);
36 std::memset(this->outbuf, 0, this->buf_size); 31 std::memset(this->outbuf, 0, this->buf_size);
37 std::memset(this->cbc_block, 0, this->buf_size); 32 std::memset(this->cbc_block, 0, this->buf_size);
38 - if (encrypt)  
39 - {  
40 - this->nrounds = rijndaelSetupEncrypt(  
41 - this->rk.getPointer(), this->key.getPointer(), keybits);  
42 - }  
43 - else  
44 - {  
45 - this->nrounds = rijndaelSetupDecrypt(  
46 - this->rk.getPointer(), this->key.getPointer(), keybits);  
47 - }  
48 - assert(this->nrounds == NROUNDS(keybits)); 33 + this->crypto->rijndael_init(encrypt, this->key.get(), key_bytes);
49 } 34 }
50 35
51 Pl_AES_PDF::~Pl_AES_PDF() 36 Pl_AES_PDF::~Pl_AES_PDF()
@@ -148,6 +133,7 @@ Pl_AES_PDF::finish() @@ -148,6 +133,7 @@ Pl_AES_PDF::finish()
148 } 133 }
149 flush(! this->disable_padding); 134 flush(! this->disable_padding);
150 } 135 }
  136 + this->crypto->rijndael_finalize();
151 getNext()->finish(); 137 getNext()->finish();
152 } 138 }
153 139
@@ -224,8 +210,7 @@ Pl_AES_PDF::flush(bool strip_padding) @@ -224,8 +210,7 @@ Pl_AES_PDF::flush(bool strip_padding)
224 this->inbuf[i] ^= this->cbc_block[i]; 210 this->inbuf[i] ^= this->cbc_block[i];
225 } 211 }
226 } 212 }
227 - rijndaelEncrypt(this->rk.getPointer(),  
228 - this->nrounds, this->inbuf, this->outbuf); 213 + this->crypto->rijndael_process(this->inbuf, this->outbuf);
229 if (this->cbc_mode) 214 if (this->cbc_mode)
230 { 215 {
231 memcpy(this->cbc_block, this->outbuf, this->buf_size); 216 memcpy(this->cbc_block, this->outbuf, this->buf_size);
@@ -233,8 +218,7 @@ Pl_AES_PDF::flush(bool strip_padding) @@ -233,8 +218,7 @@ Pl_AES_PDF::flush(bool strip_padding)
233 } 218 }
234 else 219 else
235 { 220 {
236 - rijndaelDecrypt(this->rk.getPointer(),  
237 - this->nrounds, this->inbuf, this->outbuf); 221 + this->crypto->rijndael_process(this->inbuf, this->outbuf);
238 if (this->cbc_mode) 222 if (this->cbc_mode)
239 { 223 {
240 for (unsigned int i = 0; i < this->buf_size; ++i) 224 for (unsigned int i = 0; i < this->buf_size; ++i)
libqpdf/QPDFCrypto_native.cc
@@ -66,3 +66,23 @@ QPDFCrypto_native::SHA2_digest() @@ -66,3 +66,23 @@ QPDFCrypto_native::SHA2_digest()
66 { 66 {
67 return this->sha2->getRawDigest(); 67 return this->sha2->getRawDigest();
68 } 68 }
  69 +
  70 +void
  71 +QPDFCrypto_native::rijndael_init(
  72 + bool encrypt, unsigned char const* key_data, size_t key_len)
  73 +{
  74 + this->aes_pdf = std::make_shared<AES_PDF_native>(
  75 + encrypt, key_data, key_len);
  76 +}
  77 +
  78 +void
  79 +QPDFCrypto_native::rijndael_process(unsigned char* in_data,
  80 + unsigned char* out_data)
  81 +{
  82 + this->aes_pdf->update(in_data, out_data);
  83 +}
  84 +
  85 +void
  86 +QPDFCrypto_native::rijndael_finalize()
  87 +{
  88 +}
libqpdf/build.mk
@@ -5,6 +5,7 @@ LDFLAGS_libqpdf = -Llibqpdf/$(OUTPUT_DIR) @@ -5,6 +5,7 @@ LDFLAGS_libqpdf = -Llibqpdf/$(OUTPUT_DIR)
5 LIBS_libqpdf = -lqpdf 5 LIBS_libqpdf = -lqpdf
6 6
7 SRCS_libqpdf = \ 7 SRCS_libqpdf = \
  8 + libqpdf/AES_PDF_native.cc \
8 libqpdf/BitStream.cc \ 9 libqpdf/BitStream.cc \
9 libqpdf/BitWriter.cc \ 10 libqpdf/BitWriter.cc \
10 libqpdf/Buffer.cc \ 11 libqpdf/Buffer.cc \
libqpdf/qpdf/AES_PDF_native.hh 0 → 100644
  1 +#ifndef AES_PDF_NATIVE_HH
  2 +#define AES_PDF_NATIVE_HH
  3 +
  4 +#include <cstdint>
  5 +#include <cstring>
  6 +#include <memory>
  7 +
  8 +class AES_PDF_native
  9 +{
  10 + public:
  11 + // key should be a pointer to key_bytes bytes of data
  12 + AES_PDF_native(bool encrypt, unsigned char const* key,
  13 + size_t key_bytes);
  14 + ~AES_PDF_native();
  15 +
  16 + void update(unsigned char* in_data, unsigned char* out_data);
  17 +
  18 + private:
  19 + bool encrypt;
  20 + std::unique_ptr<unsigned char[]> key;
  21 + std::unique_ptr<uint32_t[]> rk;
  22 + unsigned int nrounds;
  23 +};
  24 +
  25 +#endif // AES_PDF_NATIVE_HH
libqpdf/qpdf/Pl_AES_PDF.hh
@@ -3,9 +3,8 @@ @@ -3,9 +3,8 @@
3 3
4 #include <qpdf/Pipeline.hh> 4 #include <qpdf/Pipeline.hh>
5 #include <qpdf/qpdf-config.h> 5 #include <qpdf/qpdf-config.h>
6 -#ifdef HAVE_STDINT_H  
7 -# include <stdint.h>  
8 -#endif 6 +#include <qpdf/QPDFCryptoImpl.hh>
  7 +#include <memory>
9 8
10 // This pipeline implements AES-128 and AES-256 with CBC and block 9 // This pipeline implements AES-128 and AES-256 with CBC and block
11 // padding as specified in the PDF specification. 10 // padding as specified in the PDF specification.
@@ -51,17 +50,16 @@ class Pl_AES_PDF: public Pipeline @@ -51,17 +50,16 @@ class Pl_AES_PDF: public Pipeline
51 static unsigned int const buf_size = 16; 50 static unsigned int const buf_size = 16;
52 static bool use_static_iv; 51 static bool use_static_iv;
53 52
  53 + std::shared_ptr<QPDFCryptoImpl> crypto;
54 bool encrypt; 54 bool encrypt;
55 bool cbc_mode; 55 bool cbc_mode;
56 bool first; 56 bool first;
57 size_t offset; // offset into memory buffer 57 size_t offset; // offset into memory buffer
58 - PointerHolder<unsigned char> key;  
59 - PointerHolder<uint32_t> rk; 58 + std::unique_ptr<unsigned char[]> key;
60 unsigned char inbuf[buf_size]; 59 unsigned char inbuf[buf_size];
61 unsigned char outbuf[buf_size]; 60 unsigned char outbuf[buf_size];
62 unsigned char cbc_block[buf_size]; 61 unsigned char cbc_block[buf_size];
63 unsigned char specified_iv[buf_size]; 62 unsigned char specified_iv[buf_size];
64 - unsigned int nrounds;  
65 bool use_zero_iv; 63 bool use_zero_iv;
66 bool use_specified_iv; 64 bool use_specified_iv;
67 bool disable_padding; 65 bool disable_padding;
libqpdf/qpdf/QPDFCrypto_native.hh
@@ -6,6 +6,7 @@ @@ -6,6 +6,7 @@
6 #include <qpdf/MD5_native.hh> 6 #include <qpdf/MD5_native.hh>
7 #include <qpdf/RC4_native.hh> 7 #include <qpdf/RC4_native.hh>
8 #include <qpdf/SHA2_native.hh> 8 #include <qpdf/SHA2_native.hh>
  9 +#include <qpdf/AES_PDF_native.hh>
9 #include <memory> 10 #include <memory>
10 11
11 class QPDFCrypto_native: public QPDFCryptoImpl 12 class QPDFCrypto_native: public QPDFCryptoImpl
@@ -31,10 +32,17 @@ class QPDFCrypto_native: public QPDFCryptoImpl @@ -31,10 +32,17 @@ class QPDFCrypto_native: public QPDFCryptoImpl
31 virtual void SHA2_finalize(); 32 virtual void SHA2_finalize();
32 virtual std::string SHA2_digest(); 33 virtual std::string SHA2_digest();
33 34
  35 + virtual void rijndael_init(
  36 + bool encrypt, unsigned char const* key_data, size_t key_len);
  37 + virtual void rijndael_process(
  38 + unsigned char* in_data, unsigned char* out_data);
  39 + virtual void rijndael_finalize();
  40 +
34 private: 41 private:
35 std::shared_ptr<MD5_native> md5; 42 std::shared_ptr<MD5_native> md5;
36 std::shared_ptr<RC4_native> rc4; 43 std::shared_ptr<RC4_native> rc4;
37 std::shared_ptr<SHA2_native> sha2; 44 std::shared_ptr<SHA2_native> sha2;
  45 + std::shared_ptr<AES_PDF_native> aes_pdf;
38 }; 46 };
39 47
40 #endif // QPDFCRYPTO_NATIVE_HH 48 #endif // QPDFCRYPTO_NATIVE_HH