aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2009-10-19 02:36:51 +0200
committerJay Berkenbilt <ejb@ql.org>2009-10-19 02:36:51 +0200
commita8715c495b218c9b9388a2e20c8202a3fa73b2c1 (patch)
tree721a4a9c39d9c9fdf3a150cf64859c331d392fc2
parent09175e457852c585a68a86d43280f7e0790a4a3b (diff)
downloadqpdf-a8715c495b218c9b9388a2e20c8202a3fa73b2c1.tar.zst
add C API for R4 encryption
git-svn-id: svn+q:///qpdf/trunk@825 71b93d88-0707-0410-a8cf-f5a4172ac649
-rw-r--r--include/qpdf/QPDFWriter.hh5
-rw-r--r--include/qpdf/qpdf-c.h13
-rw-r--r--libqpdf/Pl_AES_PDF.cc22
-rw-r--r--libqpdf/QPDFWriter.cc9
-rw-r--r--libqpdf/qpdf-c.cc26
-rw-r--r--libqpdf/qpdf/Pl_AES_PDF.hh3
-rw-r--r--qpdf/qpdf-ctest.c17
-rw-r--r--qpdf/qpdf.cc11
-rw-r--r--qpdf/qpdf.testcov2
-rw-r--r--qpdf/qtest/qpdf.test1
-rw-r--r--qpdf/qtest/qpdf/c-r4.pdfbin0 -> 10881 bytes
11 files changed, 107 insertions, 2 deletions
diff --git a/include/qpdf/QPDFWriter.hh b/include/qpdf/QPDFWriter.hh
index e16c5f99..9d92ffbb 100644
--- a/include/qpdf/QPDFWriter.hh
+++ b/include/qpdf/QPDFWriter.hh
@@ -110,6 +110,11 @@ class DLL_EXPORT QPDFWriter
// suites.
void setStaticID(bool);
+ // Use a fixed initialization vector for AES-CBC encryption. This
+ // is not secure. It should be used only in test suites for
+ // creating predictable encrypted output.
+ void setStaticAesIV(bool);
+
// Suppress inclusion of comments indicating original object IDs
// when writing QDF files. This can also be useful for testing,
// particularly when using comparison of two qdf files to
diff --git a/include/qpdf/qpdf-c.h b/include/qpdf/qpdf-c.h
index fab8112b..8c112ba5 100644
--- a/include/qpdf/qpdf-c.h
+++ b/include/qpdf/qpdf-c.h
@@ -226,6 +226,12 @@ extern "C" {
DLL_EXPORT
void qpdf_set_static_ID(qpdf_data qpdf, QPDF_BOOL value);
+ /* Never use qpdf_set_static_aes_IV except in test suites to
+ * create predictable AES encrypted output.
+ */
+ DLL_EXPORT
+ void qpdf_set_static_aes_IV(qpdf_data qpdf, QPDF_BOOL value);
+
DLL_EXPORT
void qpdf_set_suppress_original_object_IDs(
qpdf_data qpdf, QPDF_BOOL value);
@@ -259,6 +265,13 @@ extern "C" {
int print, int modify);
DLL_EXPORT
+ void qpdf_set_r4_encryption_parameters(
+ qpdf_data qpdf, char const* user_password, char const* owner_password,
+ QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
+ int print, int modify,
+ QPDF_BOOL encrypt_metadata, QPDF_BOOL use_aes);
+
+ DLL_EXPORT
void qpdf_set_linearization(qpdf_data qpdf, QPDF_BOOL value);
DLL_EXPORT
diff --git a/libqpdf/Pl_AES_PDF.cc b/libqpdf/Pl_AES_PDF.cc
index 0ceb7df7..d9754981 100644
--- a/libqpdf/Pl_AES_PDF.cc
+++ b/libqpdf/Pl_AES_PDF.cc
@@ -12,6 +12,8 @@
# define srandom srand
#endif
+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]) :
Pipeline(identifier, next),
@@ -52,6 +54,12 @@ Pl_AES_PDF::disableCBC()
}
void
+Pl_AES_PDF::useStaticIV()
+{
+ use_static_iv = true;
+}
+
+void
Pl_AES_PDF::write(unsigned char* data, int len)
{
unsigned int bytes_left = len;
@@ -116,9 +124,19 @@ Pl_AES_PDF::initializeVector()
srandom((int)QUtil::get_current_time() ^ 0xcccc);
seeded_random = true;
}
- for (unsigned int i = 0; i < this->buf_size; ++i)
+ if (use_static_iv)
+ {
+ for (unsigned int i = 0; i < this->buf_size; ++i)
+ {
+ this->cbc_block[i] = 14 * (1 + i);
+ }
+ }
+ else
{
- this->cbc_block[i] = (unsigned char)((random() & 0xff0) >> 4);
+ for (unsigned int i = 0; i < this->buf_size; ++i)
+ {
+ this->cbc_block[i] = (unsigned char)((random() & 0xff0) >> 4);
+ }
}
}
diff --git a/libqpdf/QPDFWriter.cc b/libqpdf/QPDFWriter.cc
index 3c1640f7..320706b0 100644
--- a/libqpdf/QPDFWriter.cc
+++ b/libqpdf/QPDFWriter.cc
@@ -140,6 +140,15 @@ QPDFWriter::setStaticID(bool val)
}
void
+QPDFWriter::setStaticAesIV(bool val)
+{
+ if (val)
+ {
+ Pl_AES_PDF::useStaticIV();
+ }
+}
+
+void
QPDFWriter::setSuppressOriginalObjectIDs(bool val)
{
this->suppress_original_object_ids = val;
diff --git a/libqpdf/qpdf-c.cc b/libqpdf/qpdf-c.cc
index abc74c95..96de680f 100644
--- a/libqpdf/qpdf-c.cc
+++ b/libqpdf/qpdf-c.cc
@@ -313,6 +313,12 @@ void qpdf_set_static_ID(qpdf_data qpdf, QPDF_BOOL value)
qpdf->qpdf_writer->setStaticID(value);
}
+void qpdf_set_static_aes_IV(qpdf_data qpdf, QPDF_BOOL value)
+{
+ QTC::TC("qpdf", "qpdf-c called qpdf_set_static_aes_IV");
+ qpdf->qpdf_writer->setStaticAesIV(value);
+}
+
void qpdf_set_suppress_original_object_IDs(
qpdf_data qpdf, QPDF_BOOL value)
{
@@ -356,6 +362,26 @@ void qpdf_set_r3_encryption_parameters(
QPDFWriter::r3m_all));
}
+void qpdf_set_r4_encryption_parameters(
+ qpdf_data qpdf, char const* user_password, char const* owner_password,
+ QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
+ int print, int modify, QPDF_BOOL encrypt_metadata, QPDF_BOOL use_aes)
+{
+ QTC::TC("qpdf", "qpdf-c called qpdf_set_r4_encryption_parameters");
+ qpdf->qpdf_writer->setR4EncryptionParameters(
+ user_password, owner_password,
+ allow_accessibility, allow_extract,
+ ((print == QPDF_R3_PRINT_LOW) ? QPDFWriter::r3p_low :
+ (print == QPDF_R3_PRINT_NONE) ? QPDFWriter::r3p_none :
+ QPDFWriter::r3p_full),
+ ((modify == QPDF_R3_MODIFY_ANNOTATE) ? QPDFWriter::r3m_annotate :
+ (modify == QPDF_R3_MODIFY_FORM) ? QPDFWriter::r3m_form :
+ (modify == QPDF_R3_MODIFY_ASSEMBLY) ? QPDFWriter::r3m_assembly :
+ (modify == QPDF_R3_MODIFY_NONE) ? QPDFWriter::r3m_none :
+ QPDFWriter::r3m_all),
+ encrypt_metadata, use_aes);
+}
+
void qpdf_set_linearization(qpdf_data qpdf, QPDF_BOOL value)
{
QTC::TC("qpdf", "qpdf-c called qpdf_set_linearization");
diff --git a/libqpdf/qpdf/Pl_AES_PDF.hh b/libqpdf/qpdf/Pl_AES_PDF.hh
index 888ea752..084fca7b 100644
--- a/libqpdf/qpdf/Pl_AES_PDF.hh
+++ b/libqpdf/qpdf/Pl_AES_PDF.hh
@@ -20,12 +20,15 @@ class DLL_EXPORT Pl_AES_PDF: public Pipeline
// For testing only; PDF always uses CBC
void disableCBC();
+ // For testing only: use a fixed initialization vector for CBC
+ static void useStaticIV();
private:
void flush(bool discard_padding);
void initializeVector();
static unsigned int const buf_size = 16;
+ static bool use_static_iv;
bool encrypt;
bool cbc_mode;
diff --git a/qpdf/qpdf-ctest.c b/qpdf/qpdf-ctest.c
index c3e1040b..ce785a3a 100644
--- a/qpdf/qpdf-ctest.c
+++ b/qpdf/qpdf-ctest.c
@@ -229,6 +229,22 @@ static void test14(char const* infile,
report_errors();
}
+static void test15(char const* infile,
+ char const* password,
+ char const* outfile,
+ char const* outfile2)
+{
+ qpdf_read(qpdf, infile, password);
+ qpdf_init_write(qpdf, outfile);
+ qpdf_set_static_ID(qpdf, QPDF_TRUE);
+ qpdf_set_static_aes_IV(qpdf, QPDF_TRUE);
+ qpdf_set_r4_encryption_parameters(
+ qpdf, "user2", "owner2", QPDF_TRUE, QPDF_TRUE,
+ QPDF_R3_PRINT_LOW, QPDF_R3_MODIFY_ALL, QPDF_TRUE, QPDF_TRUE);
+ qpdf_write(qpdf);
+ report_errors();
+}
+
int main(int argc, char* argv[])
{
char* whoami = 0;
@@ -278,6 +294,7 @@ int main(int argc, char* argv[])
(n == 12) ? test12 :
(n == 13) ? test13 :
(n == 14) ? test14 :
+ (n == 15) ? test15 :
0);
if (fn == 0)
diff --git a/qpdf/qpdf.cc b/qpdf/qpdf.cc
index c54504b8..c614b5bf 100644
--- a/qpdf/qpdf.cc
+++ b/qpdf/qpdf.cc
@@ -146,6 +146,8 @@ These options can be useful for digging into PDF files or for use in\n\
automated test suites for software that uses the qpdf library.\n\
\n\
--static-id generate static /ID: FOR TESTING ONLY!\n\
+--static-aes-iv use a static initialization vector for AES-CBC\n\
+ This is option is not secure! FOR TESTING ONLY!\n\
--no-original-object-ids suppress original object ID comments in qdf mode\n\
--show-encryption quickly show encryption parameters\n\
--check-linearization check file integrity and linearization status\n\
@@ -604,6 +606,7 @@ int main(int argc, char* argv[])
std::string force_version;
bool static_id = false;
+ bool static_aes_iv = false;
bool suppress_original_object_id = false;
bool show_encryption = false;
bool check_linearization = false;
@@ -758,6 +761,10 @@ int main(int argc, char* argv[])
{
static_id = true;
}
+ else if (strcmp(arg, "static-aes-iv") == 0)
+ {
+ static_aes_iv = true;
+ }
else if (strcmp(arg, "no-original-object-ids") == 0)
{
suppress_original_object_id = true;
@@ -1049,6 +1056,10 @@ int main(int argc, char* argv[])
{
w.setStaticID(true);
}
+ if (static_aes_iv)
+ {
+ w.setStaticAesIV(true);
+ }
if (suppress_original_object_id)
{
w.setSuppressOriginalObjectIDs(true);
diff --git a/qpdf/qpdf.testcov b/qpdf/qpdf.testcov
index d1cf3293..dd9ec5b1 100644
--- a/qpdf/qpdf.testcov
+++ b/qpdf/qpdf.testcov
@@ -168,3 +168,5 @@ QPDF_encryption cleartext metadata 0
QPDF_encryption aes decode stream 0
QPDFWriter forcing object stream disable 0
QPDFWriter forced version disabled encryption 0
+qpdf-c called qpdf_set_r4_encryption_parameters 0
+qpdf-c called qpdf_set_static_aes_IV 0
diff --git a/qpdf/qtest/qpdf.test b/qpdf/qtest/qpdf.test
index 4ff06406..3e425254 100644
--- a/qpdf/qtest/qpdf.test
+++ b/qpdf/qtest/qpdf.test
@@ -954,6 +954,7 @@ $td->runtest("invalid password",
my @cenc = (
[11, 'hybrid-xref.pdf', "''", 'r2', ""],
[12, 'hybrid-xref.pdf', "''", 'r3', ""],
+ [15, 'hybrid-xref.pdf', "''", 'r4', ""],
[13, 'c-r2.pdf', 'user1', 'decrypt with user',
"user password: user1\n"],
[13, 'c-r3.pdf', 'owner2', 'decrypt with owner',
diff --git a/qpdf/qtest/qpdf/c-r4.pdf b/qpdf/qtest/qpdf/c-r4.pdf
new file mode 100644
index 00000000..d985109f
--- /dev/null
+++ b/qpdf/qtest/qpdf/c-r4.pdf
Binary files differ