aboutsummaryrefslogtreecommitdiffstats
path: root/libqpdf
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2012-12-28 03:37:57 +0100
committerJay Berkenbilt <ejb@ql.org>2012-12-31 11:36:50 +0100
commit9b42f526dffd5e1518ff3d83564eb09111ac5f0d (patch)
treede79d55730d0d58d31a1e4fc3babd696f9d98587 /libqpdf
parent774584163ff3d310e7c932e2a6f63b590cb736ac (diff)
downloadqpdf-9b42f526dffd5e1518ff3d83564eb09111ac5f0d.tar.zst
Update AES classes to work with 256-bit keys
Diffstat (limited to 'libqpdf')
-rw-r--r--libqpdf/Pl_AES_PDF.cc77
-rw-r--r--libqpdf/QPDFWriter.cc8
-rw-r--r--libqpdf/QPDF_encryption.cc11
-rw-r--r--libqpdf/qpdf/Pl_AES_PDF.hh22
4 files changed, 83 insertions, 35 deletions
diff --git a/libqpdf/Pl_AES_PDF.cc b/libqpdf/Pl_AES_PDF.cc
index 0f73c09c..57bf5766 100644
--- a/libqpdf/Pl_AES_PDF.cc
+++ b/libqpdf/Pl_AES_PDF.cc
@@ -15,19 +15,24 @@
bool Pl_AES_PDF::use_static_iv = false;
Pl_AES_PDF::Pl_AES_PDF(char const* identifier, Pipeline* next,
- bool encrypt, unsigned char const key[key_size]) :
+ bool encrypt, unsigned char const* key,
+ unsigned int key_bytes) :
Pipeline(identifier, next),
encrypt(encrypt),
cbc_mode(true),
first(true),
offset(0),
- nrounds(0)
+ nrounds(0),
+ use_zero_iv(false),
+ disable_padding(false)
{
- 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));
+ unsigned int keybits = 8 * key_bytes;
+ assert(key_bytes == KEYLENGTH(keybits));
+ this->key = new unsigned char[key_bytes];
+ this->rk = new uint32_t[RKLENGTH(keybits)];
+ unsigned int rk_bytes = RKLENGTH(keybits) * sizeof(uint32_t);
+ std::memcpy(this->key, key, key_bytes);
+ std::memset(this->rk, 0, rk_bytes);
std::memset(this->inbuf, 0, this->buf_size);
std::memset(this->outbuf, 0, this->buf_size);
std::memset(this->cbc_block, 0, this->buf_size);
@@ -44,7 +49,20 @@ Pl_AES_PDF::Pl_AES_PDF(char const* identifier, Pipeline* next,
Pl_AES_PDF::~Pl_AES_PDF()
{
- // nothing needed
+ delete [] this->key;
+ delete [] this->rk;
+}
+
+void
+Pl_AES_PDF::useZeroIV()
+{
+ this->use_zero_iv = true;
+}
+
+void
+Pl_AES_PDF::disablePadding()
+{
+ this->disable_padding = true;
}
void
@@ -90,13 +108,16 @@ Pl_AES_PDF::finish()
{
flush(false);
}
- // Pad as described in section 3.5.1 of version 1.7 of the PDF
- // specification, including providing an entire block of padding
- // if the input was a multiple of 16 bytes.
- unsigned char pad = (unsigned char) (this->buf_size - this->offset);
- memset(this->inbuf + this->offset, pad, pad);
- this->offset = this->buf_size;
- flush(false);
+ if (! this->disable_padding)
+ {
+ // Pad as described in section 3.5.1 of version 1.7 of the PDF
+ // specification, including providing an entire block of padding
+ // if the input was a multiple of 16 bytes.
+ unsigned char pad = (unsigned char) (this->buf_size - this->offset);
+ memset(this->inbuf + this->offset, pad, pad);
+ this->offset = this->buf_size;
+ flush(false);
+ }
}
else
{
@@ -112,7 +133,7 @@ Pl_AES_PDF::finish()
this->buf_size - this->offset);
this->offset = this->buf_size;
}
- flush(true);
+ flush(! this->disable_padding);
}
getNext()->finish();
}
@@ -136,6 +157,13 @@ Pl_AES_PDF::initializeVector()
this->cbc_block[i] = 14 * (1 + i);
}
}
+ else if (use_zero_iv)
+ {
+ for (unsigned int i = 0; i < this->buf_size; ++i)
+ {
+ this->cbc_block[i] = 0;
+ }
+ }
else
{
for (unsigned int i = 0; i < this->buf_size; ++i)
@@ -157,12 +185,21 @@ Pl_AES_PDF::flush(bool strip_padding)
{
if (encrypt)
{
- // Set cbc_block to a random initialization vector and
- // write it to the output stream
+ // Set cbc_block to the initialization vector, and if
+ // not zero, write it to the output stream.
initializeVector();
- getNext()->write(this->cbc_block, this->buf_size);
+ if (! this->use_zero_iv)
+ {
+ getNext()->write(this->cbc_block, this->buf_size);
+ }
}
- else
+ else if (this->use_zero_iv)
+ {
+ // Initialize vector with zeroes; zero vector was not
+ // written to the beginning of the input file.
+ initializeVector();
+ }
+ else
{
// Take the first block of input as the initialization
// vector. There's nothing to write at this time.
diff --git a/libqpdf/QPDFWriter.cc b/libqpdf/QPDFWriter.cc
index 963f9627..cde76af9 100644
--- a/libqpdf/QPDFWriter.cc
+++ b/libqpdf/QPDFWriter.cc
@@ -815,13 +815,14 @@ QPDFWriter::pushEncryptionFilter()
{
p = new Pl_AES_PDF(
"aes stream encryption", this->pipeline, true,
- (unsigned char*) this->cur_data_key.c_str());
+ (unsigned char*) this->cur_data_key.c_str(),
+ (unsigned int)this->cur_data_key.length());
}
else
{
p = new Pl_RC4("rc4 stream encryption", this->pipeline,
(unsigned char*) this->cur_data_key.c_str(),
- (int)this->cur_data_key.length());
+ (unsigned int)this->cur_data_key.length());
}
pushPipeline(p);
}
@@ -1415,7 +1416,8 @@ QPDFWriter::unparseObject(QPDFObjectHandle object, int level,
{
Pl_Buffer bufpl("encrypted string");
Pl_AES_PDF pl("aes encrypt string", &bufpl, true,
- (unsigned char const*)this->cur_data_key.c_str());
+ (unsigned char const*)this->cur_data_key.c_str(),
+ (unsigned int)this->cur_data_key.length());
pl.write((unsigned char*) val.c_str(), val.length());
pl.finish();
Buffer* buf = bufpl.getBuffer();
diff --git a/libqpdf/QPDF_encryption.cc b/libqpdf/QPDF_encryption.cc
index 893f93f5..43bc62ba 100644
--- a/libqpdf/QPDF_encryption.cc
+++ b/libqpdf/QPDF_encryption.cc
@@ -674,10 +674,10 @@ QPDF::decryptString(std::string& str, int objid, int generation)
if (use_aes)
{
QTC::TC("qpdf", "QPDF_encryption aes decode string");
- assert(key.length() == Pl_AES_PDF::key_size);
Pl_Buffer bufpl("decrypted string");
Pl_AES_PDF pl("aes decrypt string", &bufpl, false,
- (unsigned char const*)key.c_str());
+ (unsigned char const*)key.c_str(),
+ (unsigned int)key.length());
pl.write((unsigned char*)str.c_str(), str.length());
pl.finish();
PointerHolder<Buffer> buf = bufpl.getBuffer();
@@ -794,15 +794,16 @@ QPDF::decryptStream(Pipeline*& pipeline, int objid, int generation,
if (use_aes)
{
QTC::TC("qpdf", "QPDF_encryption aes decode stream");
- assert(key.length() == Pl_AES_PDF::key_size);
pipeline = new Pl_AES_PDF("AES stream decryption", pipeline,
- false, (unsigned char*) key.c_str());
+ false, (unsigned char*) key.c_str(),
+ (unsigned int) key.length());
}
else
{
QTC::TC("qpdf", "QPDF_encryption rc4 decode stream");
pipeline = new Pl_RC4("RC4 stream decryption", pipeline,
- (unsigned char*) key.c_str(), (int)key.length());
+ (unsigned char*) key.c_str(),
+ (unsigned int) key.length());
}
heap.push_back(pipeline);
}
diff --git a/libqpdf/qpdf/Pl_AES_PDF.hh b/libqpdf/qpdf/Pl_AES_PDF.hh
index 3947506b..72f82229 100644
--- a/libqpdf/qpdf/Pl_AES_PDF.hh
+++ b/libqpdf/qpdf/Pl_AES_PDF.hh
@@ -7,17 +7,16 @@
# include <stdint.h>
#endif
-// This pipeline implements AES-128 with CBC and block padding as
-// specified in the PDF specification.
+// This pipeline implements AES-128 and AES-256 with CBC and block
+// padding as specified in the PDF specification.
class 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;
QPDF_DLL
+ // key should be a pointer to key_bytes bytes of data
Pl_AES_PDF(char const* identifier, Pipeline* next,
- bool encrypt, unsigned char const key[key_size]);
+ bool encrypt, unsigned char const* key, unsigned int key_bytes);
QPDF_DLL
virtual ~Pl_AES_PDF();
@@ -26,6 +25,13 @@ class Pl_AES_PDF: public Pipeline
QPDF_DLL
virtual void finish();
+ // Use zero initialization vector; needed for AESV3
+ QPDF_DLL
+ void useZeroIV();
+ // Disable padding; needed for AESV3
+ QPDF_DLL
+ void disablePadding();
+
// For testing only; PDF always uses CBC
QPDF_DLL
void disableCBC();
@@ -44,12 +50,14 @@ class Pl_AES_PDF: public Pipeline
bool cbc_mode;
bool first;
size_t offset; // offset into memory buffer
- unsigned char key[key_size];
- uint32_t rk[key_size + 28];
+ unsigned char* key;
+ uint32_t* rk;
unsigned char inbuf[buf_size];
unsigned char outbuf[buf_size];
unsigned char cbc_block[buf_size];
unsigned int nrounds;
+ bool use_zero_iv;
+ bool disable_padding;
};
#endif // __PL_AES_PDF_HH__