summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2009-10-17 17:01:20 +0200
committerJay Berkenbilt <ejb@ql.org>2009-10-17 17:01:20 +0200
commit55e400376a73bcab9a4e64ecfddbf073008ac422 (patch)
treecce38c04180edfbbd684bee2e44410cefa6228e0
parent2c3b6a5c9b70a266e4528a22a03532ea84461975 (diff)
downloadqpdf-55e400376a73bcab9a4e64ecfddbf073008ac422.tar.zst
got working aes128 implementation
git-svn-id: svn+q:///qpdf/trunk@809 71b93d88-0707-0410-a8cf-f5a4172ac649
-rw-r--r--README9
-rw-r--r--libqpdf/Pl_AES_PDF.cc42
-rw-r--r--libqpdf/build.mk3
-rw-r--r--libqpdf/qpdf/Pl_AES_PDF.hh14
-rw-r--r--libqpdf/qpdf/rijndael.h13
-rw-r--r--libqpdf/rijndael.cc4
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 <cstring>
#include <assert.h>
#include <stdexcept>
+#include <qpdf/rijndael.h>
+
+// 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 <qpdf/Pipeline.hh>
+// 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 <qpdf/qpdf-config.h>
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#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] =