Commit 55e400376a73bcab9a4e64ecfddbf073008ac422
1 parent
2c3b6a5c
got working aes128 implementation
git-svn-id: svn+q:///qpdf/trunk@809 71b93d88-0707-0410-a8cf-f5a4172ac649
Showing
6 changed files
with
63 additions
and
22 deletions
README
| ... | ... | @@ -33,6 +33,15 @@ The sources to PCRE can be independently obtained from |
| 33 | 33 | |
| 34 | 34 | ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/ |
| 35 | 35 | |
| 36 | +The Rijndael encryption implementation used as the basis for AES | |
| 37 | +encryption and decryption support comes from Philip J. Erdelsky's | |
| 38 | +public domain implementation. The files libqpdf/rijndael.cc and | |
| 39 | +libqpdf/qpdf/rijndael.h remain in the public domain. They were | |
| 40 | +obtained from | |
| 41 | + | |
| 42 | + http://www.efgh.com/software/rijndael.htm | |
| 43 | + http://www.efgh.com/software/rijndael.txt | |
| 44 | + | |
| 36 | 45 | |
| 37 | 46 | Building on UNIX/Linux |
| 38 | 47 | ====================== | ... | ... |
libqpdf/Pl_AES_PDF.cc
| ... | ... | @@ -3,20 +3,38 @@ |
| 3 | 3 | #include <cstring> |
| 4 | 4 | #include <assert.h> |
| 5 | 5 | #include <stdexcept> |
| 6 | +#include <qpdf/rijndael.h> | |
| 7 | + | |
| 8 | +// XXX Still need CBC | |
| 6 | 9 | |
| 7 | 10 | Pl_AES_PDF::Pl_AES_PDF(char const* identifier, Pipeline* next, |
| 8 | - bool encrypt, unsigned char* key_data) : | |
| 11 | + bool encrypt, unsigned char key[key_size]) : | |
| 9 | 12 | Pipeline(identifier, next), |
| 10 | 13 | encrypt(encrypt), |
| 11 | - offset(0) | |
| 14 | + offset(0), | |
| 15 | + nrounds(0) | |
| 12 | 16 | { |
| 13 | - std::memset(this->buf, 0, this->buf_size); | |
| 14 | - // XXX init | |
| 17 | + static int const keybits = 128; | |
| 18 | + assert(key_size == KEYLENGTH(keybits)); | |
| 19 | + assert(sizeof(this->rk) / sizeof(uint32_t) == RKLENGTH(keybits)); | |
| 20 | + std::memcpy(this->key, key, key_size); | |
| 21 | + std::memset(this->rk, 0, sizeof(this->rk)); | |
| 22 | + std::memset(this->inbuf, 0, this->buf_size); | |
| 23 | + std::memset(this->outbuf, 0, this->buf_size); | |
| 24 | + if (encrypt) | |
| 25 | + { | |
| 26 | + this->nrounds = rijndaelSetupEncrypt(this->rk, this->key, keybits); | |
| 27 | + } | |
| 28 | + else | |
| 29 | + { | |
| 30 | + this->nrounds = rijndaelSetupDecrypt(this->rk, this->key, keybits); | |
| 31 | + } | |
| 32 | + assert(this->nrounds == NROUNDS(keybits)); | |
| 15 | 33 | } |
| 16 | 34 | |
| 17 | 35 | Pl_AES_PDF::~Pl_AES_PDF() |
| 18 | 36 | { |
| 19 | - // XXX finalize | |
| 37 | + // nothing needed | |
| 20 | 38 | } |
| 21 | 39 | |
| 22 | 40 | void |
| ... | ... | @@ -35,7 +53,7 @@ Pl_AES_PDF::write(unsigned char* data, int len) |
| 35 | 53 | unsigned int available = this->buf_size - this->offset; |
| 36 | 54 | int bytes = (bytes_left < available ? bytes_left : available); |
| 37 | 55 | bytes_left -= bytes; |
| 38 | - std::memcpy(this->buf + this->offset, p, bytes); | |
| 56 | + std::memcpy(this->inbuf + this->offset, p, bytes); | |
| 39 | 57 | this->offset += bytes; |
| 40 | 58 | p += bytes; |
| 41 | 59 | } |
| ... | ... | @@ -54,7 +72,7 @@ Pl_AES_PDF::finish() |
| 54 | 72 | // specification, including providing an entire block of padding |
| 55 | 73 | // if the input was a multiple of 16 bytes. |
| 56 | 74 | unsigned char pad = this->buf_size - this->offset; |
| 57 | - memset(this->buf + this->offset, pad, pad); | |
| 75 | + memset(this->inbuf + this->offset, pad, pad); | |
| 58 | 76 | this->offset = this->buf_size; |
| 59 | 77 | flush(false); |
| 60 | 78 | } |
| ... | ... | @@ -78,22 +96,22 @@ Pl_AES_PDF::flush(bool strip_padding) |
| 78 | 96 | assert(this->offset == this->buf_size); |
| 79 | 97 | if (this->encrypt) |
| 80 | 98 | { |
| 81 | - // XXX encrypt this->buf | |
| 99 | + rijndaelEncrypt(this->rk, this->nrounds, this->inbuf, this->outbuf); | |
| 82 | 100 | } |
| 83 | 101 | else |
| 84 | 102 | { |
| 85 | - // XXX decrypt this->buf | |
| 103 | + rijndaelDecrypt(this->rk, this->nrounds, this->inbuf, this->outbuf); | |
| 86 | 104 | } |
| 87 | 105 | unsigned int bytes = this->buf_size; |
| 88 | 106 | if (strip_padding) |
| 89 | 107 | { |
| 90 | - unsigned char last = this->buf[this->buf_size - 1]; | |
| 108 | + unsigned char last = this->outbuf[this->buf_size - 1]; | |
| 91 | 109 | if (last <= this->buf_size) |
| 92 | 110 | { |
| 93 | 111 | bool strip = true; |
| 94 | 112 | for (unsigned int i = 1; i <= last; ++i) |
| 95 | 113 | { |
| 96 | - if (this->buf[this->buf_size - i] != last) | |
| 114 | + if (this->outbuf[this->buf_size - i] != last) | |
| 97 | 115 | { |
| 98 | 116 | strip = false; |
| 99 | 117 | break; |
| ... | ... | @@ -105,6 +123,6 @@ Pl_AES_PDF::flush(bool strip_padding) |
| 105 | 123 | } |
| 106 | 124 | } |
| 107 | 125 | } |
| 108 | - getNext()->write(this->buf, bytes); | |
| 126 | + getNext()->write(this->outbuf, bytes); | |
| 109 | 127 | this->offset = 0; |
| 110 | 128 | } | ... | ... |
libqpdf/build.mk
libqpdf/qpdf/Pl_AES_PDF.hh
| ... | ... | @@ -3,13 +3,16 @@ |
| 3 | 3 | |
| 4 | 4 | #include <qpdf/Pipeline.hh> |
| 5 | 5 | |
| 6 | +// This pipeline implements AES-128 with CBC and block padding as | |
| 7 | +// specified in the PDF specification. | |
| 8 | + | |
| 6 | 9 | class DLL_EXPORT Pl_AES_PDF: public Pipeline |
| 7 | 10 | { |
| 8 | 11 | public: |
| 9 | 12 | // key_data should be a pointer to key_size bytes of data |
| 10 | 13 | static unsigned int const key_size = 16; |
| 11 | 14 | Pl_AES_PDF(char const* identifier, Pipeline* next, |
| 12 | - bool encrypt, unsigned char* key_data); | |
| 15 | + bool encrypt, unsigned char key[key_size]); | |
| 13 | 16 | virtual ~Pl_AES_PDF(); |
| 14 | 17 | |
| 15 | 18 | virtual void write(unsigned char* data, int len); |
| ... | ... | @@ -18,10 +21,15 @@ class DLL_EXPORT Pl_AES_PDF: public Pipeline |
| 18 | 21 | private: |
| 19 | 22 | void flush(bool discard_padding); |
| 20 | 23 | |
| 24 | + static unsigned int const buf_size = 16; | |
| 25 | + | |
| 21 | 26 | bool encrypt; |
| 22 | 27 | unsigned int offset; |
| 23 | - static unsigned int const buf_size = 16; | |
| 24 | - unsigned char buf[buf_size]; | |
| 28 | + unsigned char key[key_size]; | |
| 29 | + uint32_t rk[key_size + 28]; | |
| 30 | + unsigned char inbuf[buf_size]; | |
| 31 | + unsigned char outbuf[buf_size]; | |
| 32 | + unsigned int nrounds; | |
| 25 | 33 | }; |
| 26 | 34 | |
| 27 | 35 | #endif // __PL_AES_PDF_HH__ | ... | ... |
libqpdf/qpdf/rijndael.h
| 1 | 1 | #ifndef H__RIJNDAEL |
| 2 | 2 | #define H__RIJNDAEL |
| 3 | 3 | |
| 4 | -int rijndaelSetupEncrypt(unsigned long *rk, const unsigned char *key, | |
| 4 | +#include <qpdf/qpdf-config.h> | |
| 5 | +#ifdef HAVE_INTTYPES_H | |
| 6 | +# include <inttypes.h> | |
| 7 | +#endif | |
| 8 | + | |
| 9 | +int rijndaelSetupEncrypt(uint32_t *rk, const unsigned char *key, | |
| 5 | 10 | int keybits); |
| 6 | -int rijndaelSetupDecrypt(unsigned long *rk, const unsigned char *key, | |
| 11 | +int rijndaelSetupDecrypt(uint32_t *rk, const unsigned char *key, | |
| 7 | 12 | int keybits); |
| 8 | -void rijndaelEncrypt(const unsigned long *rk, int nrounds, | |
| 13 | +void rijndaelEncrypt(const uint32_t *rk, int nrounds, | |
| 9 | 14 | const unsigned char plaintext[16], unsigned char ciphertext[16]); |
| 10 | -void rijndaelDecrypt(const unsigned long *rk, int nrounds, | |
| 15 | +void rijndaelDecrypt(const uint32_t *rk, int nrounds, | |
| 11 | 16 | const unsigned char ciphertext[16], unsigned char plaintext[16]); |
| 12 | 17 | |
| 13 | 18 | #define KEYLENGTH(keybits) ((keybits)/8) | ... | ... |