Commit 55e400376a73bcab9a4e64ecfddbf073008ac422

Authored by Jay Berkenbilt
1 parent 2c3b6a5c

got working aes128 implementation

git-svn-id: svn+q:///qpdf/trunk@809 71b93d88-0707-0410-a8cf-f5a4172ac649
@@ -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
1 #define FULL_UNROLL 1 #define FULL_UNROLL
2 2
3 -#include "rijndael.h" 3 +#include "qpdf/rijndael.h"
4 4
5 -typedef unsigned long u32; 5 +typedef uint32_t u32;
6 typedef unsigned char u8; 6 typedef unsigned char u8;
7 7
8 static const u32 Te0[256] = 8 static const u32 Te0[256] =