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 73 unsigned char* out_data = 0) = 0;
74 74 QPDF_DLL
75 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 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 3 #include <cstring>
4 4 #include <assert.h>
5 5 #include <stdexcept>
6   -#include <qpdf/rijndael.h>
7 6 #include <qpdf/QIntC.hh>
  7 +#include <qpdf/QPDFCryptoProvider.hh>
8 8 #include <string>
9 9 #include <stdlib.h>
10 10  
... ... @@ -14,38 +14,23 @@ Pl_AES_PDF::Pl_AES_PDF(char const* identifier, Pipeline* next,
14 14 bool encrypt, unsigned char const* key,
15 15 size_t key_bytes) :
16 16 Pipeline(identifier, next),
  17 + crypto(QPDFCryptoProvider::getImpl()),
17 18 encrypt(encrypt),
18 19 cbc_mode(true),
19 20 first(true),
20 21 offset(0),
21   - nrounds(0),
22 22 use_zero_iv(false),
23 23 use_specified_iv(false),
24 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 30 std::memset(this->inbuf, 0, this->buf_size);
36 31 std::memset(this->outbuf, 0, this->buf_size);
37 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 36 Pl_AES_PDF::~Pl_AES_PDF()
... ... @@ -148,6 +133,7 @@ Pl_AES_PDF::finish()
148 133 }
149 134 flush(! this->disable_padding);
150 135 }
  136 + this->crypto->rijndael_finalize();
151 137 getNext()->finish();
152 138 }
153 139  
... ... @@ -224,8 +210,7 @@ Pl_AES_PDF::flush(bool strip_padding)
224 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 214 if (this->cbc_mode)
230 215 {
231 216 memcpy(this->cbc_block, this->outbuf, this->buf_size);
... ... @@ -233,8 +218,7 @@ Pl_AES_PDF::flush(bool strip_padding)
233 218 }
234 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 222 if (this->cbc_mode)
239 223 {
240 224 for (unsigned int i = 0; i < this->buf_size; ++i)
... ...
libqpdf/QPDFCrypto_native.cc
... ... @@ -66,3 +66,23 @@ QPDFCrypto_native::SHA2_digest()
66 66 {
67 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 5 LIBS_libqpdf = -lqpdf
6 6  
7 7 SRCS_libqpdf = \
  8 + libqpdf/AES_PDF_native.cc \
8 9 libqpdf/BitStream.cc \
9 10 libqpdf/BitWriter.cc \
10 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 3  
4 4 #include <qpdf/Pipeline.hh>
5 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 9 // This pipeline implements AES-128 and AES-256 with CBC and block
11 10 // padding as specified in the PDF specification.
... ... @@ -51,17 +50,16 @@ class Pl_AES_PDF: public Pipeline
51 50 static unsigned int const buf_size = 16;
52 51 static bool use_static_iv;
53 52  
  53 + std::shared_ptr<QPDFCryptoImpl> crypto;
54 54 bool encrypt;
55 55 bool cbc_mode;
56 56 bool first;
57 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 59 unsigned char inbuf[buf_size];
61 60 unsigned char outbuf[buf_size];
62 61 unsigned char cbc_block[buf_size];
63 62 unsigned char specified_iv[buf_size];
64   - unsigned int nrounds;
65 63 bool use_zero_iv;
66 64 bool use_specified_iv;
67 65 bool disable_padding;
... ...
libqpdf/qpdf/QPDFCrypto_native.hh
... ... @@ -6,6 +6,7 @@
6 6 #include <qpdf/MD5_native.hh>
7 7 #include <qpdf/RC4_native.hh>
8 8 #include <qpdf/SHA2_native.hh>
  9 +#include <qpdf/AES_PDF_native.hh>
9 10 #include <memory>
10 11  
11 12 class QPDFCrypto_native: public QPDFCryptoImpl
... ... @@ -31,10 +32,17 @@ class QPDFCrypto_native: public QPDFCryptoImpl
31 32 virtual void SHA2_finalize();
32 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 41 private:
35 42 std::shared_ptr<MD5_native> md5;
36 43 std::shared_ptr<RC4_native> rc4;
37 44 std::shared_ptr<SHA2_native> sha2;
  45 + std::shared_ptr<AES_PDF_native> aes_pdf;
38 46 };
39 47  
40 48 #endif // QPDFCRYPTO_NATIVE_HH
... ...