From 55e400376a73bcab9a4e64ecfddbf073008ac422 Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Sat, 17 Oct 2009 15:01:20 +0000 Subject: got working aes128 implementation git-svn-id: svn+q:///qpdf/trunk@809 71b93d88-0707-0410-a8cf-f5a4172ac649 --- README | 9 +++++++++ libqpdf/Pl_AES_PDF.cc | 42 ++++++++++++++++++++++++++++++------------ libqpdf/build.mk | 3 ++- libqpdf/qpdf/Pl_AES_PDF.hh | 14 +++++++++++--- libqpdf/qpdf/rijndael.h | 13 +++++++++---- libqpdf/rijndael.cc | 4 ++-- 6 files changed, 63 insertions(+), 22 deletions(-) diff --git a/README b/README index 2e74f388..e88c568c 100644 --- a/README +++ b/README @@ -33,6 +33,15 @@ The sources to PCRE can be independently obtained from ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/ +The Rijndael encryption implementation used as the basis for AES +encryption and decryption support comes from Philip J. Erdelsky's +public domain implementation. The files libqpdf/rijndael.cc and +libqpdf/qpdf/rijndael.h remain in the public domain. They were +obtained from + + http://www.efgh.com/software/rijndael.htm + http://www.efgh.com/software/rijndael.txt + Building on UNIX/Linux ====================== diff --git a/libqpdf/Pl_AES_PDF.cc b/libqpdf/Pl_AES_PDF.cc index f2e58af0..26dc58ae 100644 --- a/libqpdf/Pl_AES_PDF.cc +++ b/libqpdf/Pl_AES_PDF.cc @@ -3,20 +3,38 @@ #include #include #include +#include + +// XXX Still need CBC Pl_AES_PDF::Pl_AES_PDF(char const* identifier, Pipeline* next, - bool encrypt, unsigned char* key_data) : + bool encrypt, unsigned char key[key_size]) : Pipeline(identifier, next), encrypt(encrypt), - offset(0) + offset(0), + nrounds(0) { - std::memset(this->buf, 0, this->buf_size); - // XXX init + static int const keybits = 128; + assert(key_size == KEYLENGTH(keybits)); + assert(sizeof(this->rk) / sizeof(uint32_t) == RKLENGTH(keybits)); + std::memcpy(this->key, key, key_size); + std::memset(this->rk, 0, sizeof(this->rk)); + std::memset(this->inbuf, 0, this->buf_size); + std::memset(this->outbuf, 0, this->buf_size); + if (encrypt) + { + this->nrounds = rijndaelSetupEncrypt(this->rk, this->key, keybits); + } + else + { + this->nrounds = rijndaelSetupDecrypt(this->rk, this->key, keybits); + } + assert(this->nrounds == NROUNDS(keybits)); } Pl_AES_PDF::~Pl_AES_PDF() { - // XXX finalize + // nothing needed } void @@ -35,7 +53,7 @@ Pl_AES_PDF::write(unsigned char* data, int len) unsigned int available = this->buf_size - this->offset; int bytes = (bytes_left < available ? bytes_left : available); bytes_left -= bytes; - std::memcpy(this->buf + this->offset, p, bytes); + std::memcpy(this->inbuf + this->offset, p, bytes); this->offset += bytes; p += bytes; } @@ -54,7 +72,7 @@ Pl_AES_PDF::finish() // specification, including providing an entire block of padding // if the input was a multiple of 16 bytes. unsigned char pad = this->buf_size - this->offset; - memset(this->buf + this->offset, pad, pad); + memset(this->inbuf + this->offset, pad, pad); this->offset = this->buf_size; flush(false); } @@ -78,22 +96,22 @@ Pl_AES_PDF::flush(bool strip_padding) assert(this->offset == this->buf_size); if (this->encrypt) { - // XXX encrypt this->buf + rijndaelEncrypt(this->rk, this->nrounds, this->inbuf, this->outbuf); } else { - // XXX decrypt this->buf + rijndaelDecrypt(this->rk, this->nrounds, this->inbuf, this->outbuf); } unsigned int bytes = this->buf_size; if (strip_padding) { - unsigned char last = this->buf[this->buf_size - 1]; + unsigned char last = this->outbuf[this->buf_size - 1]; if (last <= this->buf_size) { bool strip = true; for (unsigned int i = 1; i <= last; ++i) { - if (this->buf[this->buf_size - i] != last) + if (this->outbuf[this->buf_size - i] != last) { strip = false; break; @@ -105,6 +123,6 @@ Pl_AES_PDF::flush(bool strip_padding) } } } - getNext()->write(this->buf, bytes); + getNext()->write(this->outbuf, bytes); this->offset = 0; } diff --git a/libqpdf/build.mk b/libqpdf/build.mk index 7b71cf61..89ca5d9f 100644 --- a/libqpdf/build.mk +++ b/libqpdf/build.mk @@ -48,7 +48,8 @@ SRCS_libqpdf = \ libqpdf/QTC.cc \ libqpdf/QUtil.cc \ libqpdf/RC4.cc \ - libqpdf/qpdf-c.cc + libqpdf/qpdf-c.cc \ + libqpdf/rijndael.cc # ----- diff --git a/libqpdf/qpdf/Pl_AES_PDF.hh b/libqpdf/qpdf/Pl_AES_PDF.hh index 6939abb8..442c9bf3 100644 --- a/libqpdf/qpdf/Pl_AES_PDF.hh +++ b/libqpdf/qpdf/Pl_AES_PDF.hh @@ -3,13 +3,16 @@ #include +// This pipeline implements AES-128 with CBC and block padding as +// specified in the PDF specification. + class DLL_EXPORT Pl_AES_PDF: public Pipeline { public: // key_data should be a pointer to key_size bytes of data static unsigned int const key_size = 16; Pl_AES_PDF(char const* identifier, Pipeline* next, - bool encrypt, unsigned char* key_data); + bool encrypt, unsigned char key[key_size]); virtual ~Pl_AES_PDF(); virtual void write(unsigned char* data, int len); @@ -18,10 +21,15 @@ class DLL_EXPORT Pl_AES_PDF: public Pipeline private: void flush(bool discard_padding); + static unsigned int const buf_size = 16; + bool encrypt; unsigned int offset; - static unsigned int const buf_size = 16; - unsigned char buf[buf_size]; + unsigned char key[key_size]; + uint32_t rk[key_size + 28]; + unsigned char inbuf[buf_size]; + unsigned char outbuf[buf_size]; + unsigned int nrounds; }; #endif // __PL_AES_PDF_HH__ diff --git a/libqpdf/qpdf/rijndael.h b/libqpdf/qpdf/rijndael.h index 9394a5b8..22037e1e 100644 --- a/libqpdf/qpdf/rijndael.h +++ b/libqpdf/qpdf/rijndael.h @@ -1,13 +1,18 @@ #ifndef H__RIJNDAEL #define H__RIJNDAEL -int rijndaelSetupEncrypt(unsigned long *rk, const unsigned char *key, +#include +#ifdef HAVE_INTTYPES_H +# include +#endif + +int rijndaelSetupEncrypt(uint32_t *rk, const unsigned char *key, int keybits); -int rijndaelSetupDecrypt(unsigned long *rk, const unsigned char *key, +int rijndaelSetupDecrypt(uint32_t *rk, const unsigned char *key, int keybits); -void rijndaelEncrypt(const unsigned long *rk, int nrounds, +void rijndaelEncrypt(const uint32_t *rk, int nrounds, const unsigned char plaintext[16], unsigned char ciphertext[16]); -void rijndaelDecrypt(const unsigned long *rk, int nrounds, +void rijndaelDecrypt(const uint32_t *rk, int nrounds, const unsigned char ciphertext[16], unsigned char plaintext[16]); #define KEYLENGTH(keybits) ((keybits)/8) diff --git a/libqpdf/rijndael.cc b/libqpdf/rijndael.cc index 2d51535c..64748d82 100644 --- a/libqpdf/rijndael.cc +++ b/libqpdf/rijndael.cc @@ -1,8 +1,8 @@ #define FULL_UNROLL -#include "rijndael.h" +#include "qpdf/rijndael.h" -typedef unsigned long u32; +typedef uint32_t u32; typedef unsigned char u8; static const u32 Te0[256] = -- cgit v1.2.3-70-g09d2