2
1
mirror of https://github.com/qpdf/qpdf.git synced 2024-06-03 10:50:53 +00:00

got working aes128 implementation

git-svn-id: svn+q:///qpdf/trunk@809 71b93d88-0707-0410-a8cf-f5a4172ac649
This commit is contained in:
Jay Berkenbilt 2009-10-17 15:01:20 +00:00
parent 2c3b6a5c9b
commit 55e400376a
6 changed files with 63 additions and 22 deletions

9
README
View File

@ -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
======================

View File

@ -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;
}

View File

@ -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
# -----

View File

@ -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__

View File

@ -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)

View File

@ -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] =