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,6 +33,15 @@ The sources to PCRE can be independently obtained from | ||
| 33 | 33 | ||
| 34 | ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/ | 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 | Building on UNIX/Linux | 46 | Building on UNIX/Linux |
| 38 | ====================== | 47 | ====================== |
libqpdf/Pl_AES_PDF.cc
| @@ -3,20 +3,38 @@ | @@ -3,20 +3,38 @@ | ||
| 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 | + | ||
| 8 | +// XXX Still need CBC | ||
| 6 | 9 | ||
| 7 | Pl_AES_PDF::Pl_AES_PDF(char const* identifier, Pipeline* next, | 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 | Pipeline(identifier, next), | 12 | Pipeline(identifier, next), |
| 10 | encrypt(encrypt), | 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 | Pl_AES_PDF::~Pl_AES_PDF() | 35 | Pl_AES_PDF::~Pl_AES_PDF() |
| 18 | { | 36 | { |
| 19 | - // XXX finalize | 37 | + // nothing needed |
| 20 | } | 38 | } |
| 21 | 39 | ||
| 22 | void | 40 | void |
| @@ -35,7 +53,7 @@ Pl_AES_PDF::write(unsigned char* data, int len) | @@ -35,7 +53,7 @@ Pl_AES_PDF::write(unsigned char* data, int len) | ||
| 35 | unsigned int available = this->buf_size - this->offset; | 53 | unsigned int available = this->buf_size - this->offset; |
| 36 | int bytes = (bytes_left < available ? bytes_left : available); | 54 | int bytes = (bytes_left < available ? bytes_left : available); |
| 37 | bytes_left -= bytes; | 55 | bytes_left -= bytes; |
| 38 | - std::memcpy(this->buf + this->offset, p, bytes); | 56 | + std::memcpy(this->inbuf + this->offset, p, bytes); |
| 39 | this->offset += bytes; | 57 | this->offset += bytes; |
| 40 | p += bytes; | 58 | p += bytes; |
| 41 | } | 59 | } |
| @@ -54,7 +72,7 @@ Pl_AES_PDF::finish() | @@ -54,7 +72,7 @@ Pl_AES_PDF::finish() | ||
| 54 | // specification, including providing an entire block of padding | 72 | // specification, including providing an entire block of padding |
| 55 | // if the input was a multiple of 16 bytes. | 73 | // if the input was a multiple of 16 bytes. |
| 56 | unsigned char pad = this->buf_size - this->offset; | 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 | this->offset = this->buf_size; | 76 | this->offset = this->buf_size; |
| 59 | flush(false); | 77 | flush(false); |
| 60 | } | 78 | } |
| @@ -78,22 +96,22 @@ Pl_AES_PDF::flush(bool strip_padding) | @@ -78,22 +96,22 @@ Pl_AES_PDF::flush(bool strip_padding) | ||
| 78 | assert(this->offset == this->buf_size); | 96 | assert(this->offset == this->buf_size); |
| 79 | if (this->encrypt) | 97 | if (this->encrypt) |
| 80 | { | 98 | { |
| 81 | - // XXX encrypt this->buf | 99 | + rijndaelEncrypt(this->rk, this->nrounds, this->inbuf, this->outbuf); |
| 82 | } | 100 | } |
| 83 | else | 101 | else |
| 84 | { | 102 | { |
| 85 | - // XXX decrypt this->buf | 103 | + rijndaelDecrypt(this->rk, this->nrounds, this->inbuf, this->outbuf); |
| 86 | } | 104 | } |
| 87 | unsigned int bytes = this->buf_size; | 105 | unsigned int bytes = this->buf_size; |
| 88 | if (strip_padding) | 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 | if (last <= this->buf_size) | 109 | if (last <= this->buf_size) |
| 92 | { | 110 | { |
| 93 | bool strip = true; | 111 | bool strip = true; |
| 94 | for (unsigned int i = 1; i <= last; ++i) | 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 | strip = false; | 116 | strip = false; |
| 99 | break; | 117 | break; |
| @@ -105,6 +123,6 @@ Pl_AES_PDF::flush(bool strip_padding) | @@ -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 | this->offset = 0; | 127 | this->offset = 0; |
| 110 | } | 128 | } |
libqpdf/build.mk
| @@ -48,7 +48,8 @@ SRCS_libqpdf = \ | @@ -48,7 +48,8 @@ SRCS_libqpdf = \ | ||
| 48 | libqpdf/QTC.cc \ | 48 | libqpdf/QTC.cc \ |
| 49 | libqpdf/QUtil.cc \ | 49 | libqpdf/QUtil.cc \ |
| 50 | libqpdf/RC4.cc \ | 50 | libqpdf/RC4.cc \ |
| 51 | - libqpdf/qpdf-c.cc | 51 | + libqpdf/qpdf-c.cc \ |
| 52 | + libqpdf/rijndael.cc | ||
| 52 | 53 | ||
| 53 | # ----- | 54 | # ----- |
| 54 | 55 |
libqpdf/qpdf/Pl_AES_PDF.hh
| @@ -3,13 +3,16 @@ | @@ -3,13 +3,16 @@ | ||
| 3 | 3 | ||
| 4 | #include <qpdf/Pipeline.hh> | 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 | class DLL_EXPORT Pl_AES_PDF: public Pipeline | 9 | class DLL_EXPORT Pl_AES_PDF: public Pipeline |
| 7 | { | 10 | { |
| 8 | public: | 11 | public: |
| 9 | // key_data should be a pointer to key_size bytes of data | 12 | // key_data should be a pointer to key_size bytes of data |
| 10 | static unsigned int const key_size = 16; | 13 | static unsigned int const key_size = 16; |
| 11 | Pl_AES_PDF(char const* identifier, Pipeline* next, | 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 | virtual ~Pl_AES_PDF(); | 16 | virtual ~Pl_AES_PDF(); |
| 14 | 17 | ||
| 15 | virtual void write(unsigned char* data, int len); | 18 | virtual void write(unsigned char* data, int len); |
| @@ -18,10 +21,15 @@ class DLL_EXPORT Pl_AES_PDF: public Pipeline | @@ -18,10 +21,15 @@ class DLL_EXPORT Pl_AES_PDF: public Pipeline | ||
| 18 | private: | 21 | private: |
| 19 | void flush(bool discard_padding); | 22 | void flush(bool discard_padding); |
| 20 | 23 | ||
| 24 | + static unsigned int const buf_size = 16; | ||
| 25 | + | ||
| 21 | bool encrypt; | 26 | bool encrypt; |
| 22 | unsigned int offset; | 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 | #endif // __PL_AES_PDF_HH__ | 35 | #endif // __PL_AES_PDF_HH__ |
libqpdf/qpdf/rijndael.h
| 1 | #ifndef H__RIJNDAEL | 1 | #ifndef H__RIJNDAEL |
| 2 | #define H__RIJNDAEL | 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 | int keybits); | 10 | int keybits); |
| 6 | -int rijndaelSetupDecrypt(unsigned long *rk, const unsigned char *key, | 11 | +int rijndaelSetupDecrypt(uint32_t *rk, const unsigned char *key, |
| 7 | int keybits); | 12 | int keybits); |
| 8 | -void rijndaelEncrypt(const unsigned long *rk, int nrounds, | 13 | +void rijndaelEncrypt(const uint32_t *rk, int nrounds, |
| 9 | const unsigned char plaintext[16], unsigned char ciphertext[16]); | 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 | const unsigned char ciphertext[16], unsigned char plaintext[16]); | 16 | const unsigned char ciphertext[16], unsigned char plaintext[16]); |
| 12 | 17 | ||
| 13 | #define KEYLENGTH(keybits) ((keybits)/8) | 18 | #define KEYLENGTH(keybits) ((keybits)/8) |
libqpdf/rijndael.cc